2006-03-07 Jeffrey Altman <jaltman@mit.edu>
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 8 Mar 2006 15:36:15 +0000 (15:36 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 8 Mar 2006 15:36:15 +0000 (15:36 +0000)
nidmgr32.dll (1.0.2.1)

- Attempting to obtain new credentials for a principal name that
  contains numbers may result in a 'Identity not specified'
  error. Fixed.

- If an invalid identity name was specified, an 'Identity not
  specified' error is reported without specifying that the cause was
  an invalid name.  Fixed: reports proper error.

- Identity names were being validated at the application layer before
  being sent to the identity provider.  This may cause valid names to
  be marked as invalid if the identity provider and the application
  disagree on what a valid name is.  Fixed: identity name validation
  is solely a function of the identity provider.

- Canonicalizing an identity name that contained certain characters
  failed due to a validation error.  Fixed.

- Possible deadlock in the new credentials dialog.  (If one plugin
  tries to synchronize custom prompter values from the plugin thread,
  while the UI thread tries to obtain a lock on the new credentials
  data, a deadlock occurs.) Fixed.

- State information for configuration panels may persist between two
  invocations of the configuration window.  Fixed to clean up state
  information properly.

- The UI library now has full support for custom actions and custom
  menus.

- When there are queued alerts and a normal alert is shown, a 'next
  alert...' button appears in the alert which lets the user view the
  next queued alert.  However, if the alert which is displayed
  requires the user to select a command button, selecting the 'next'
  button would be the equivalent of cancelling out of the alert and
  viewing the next one.  The library was updated to not show the
  'next' button if the alert requires user interaction.

- Credential renewal on half-lifes is now supported as a configurable
  option.

- Destroying all credentials on exiting netidmgr is a configurable
  option.

- Debug logging to a file has been added

netidmgr.exe (1.0.2.1)

- Selecting 'Ok' in the configuration window didn't notify all the
  configuration panels to apply the changes.  Fixed.

- PgUp / PgDn / Shift+PgUp / Shift+PgDn keys now work as expected.

- Root level configuration nodes in the Options dialog now also appear
  on the Options menu.  Configuration nodes that are registered at the
  root level are automatically added to the menu.

- The UI now has full support for custom actions and custom menus.

- The UI does not automatically add submenus for actions which are
  associated with menus unless the declaration specifies that it
  should be rendered as a submenu.

- When displaying alerts, the first button of the alert is always made
  the default.

- 'Change summary' button in the configuration dialog was removed,
  since it was unused and unnecessary.

- Ticket icons are displayed in the status column for all credentials.
  Clicking an icon opens the properties dialog for that credential.

- The UI now has View by Type functionality

- The UI now has Column selection and reorganization.  The choice
  of columns and their order are preserved between restarts.

- Handle multiple copies of NetIDMgr.exe being started with different
  version numbers.  Higher version number wins.

krb4cred.dll (1.0.2.1)

- During new credentials acquisition, under some circumstances, the
  Kerberos 4 plugin would not notify NetIDMgr about the state of the
  Kerberos 4 ticket acquisition.  This results in other plugins (such
  as AFS) which are depending on the feedback to fail.  Fixed.

krb5cred.dll (1.0.2.1)

- If no password is entered while obtaining new credentials, a new TGT
  will not be obtained, but the new credentials operation will not
  fail if there already is a TGT.  Added check to see if the TGT is
  expired and fail the operation if no valid TGT is found.

- The identity provider can set the Krb5 CCName property for an
  identity incorrectly if there is more than one credential cache
  containing tickets for the same principal.  Fixed.

- When enumerating ccaches, krb5_cc_resolve was being called with the
  name of the ccache without a type prefix.  Fixed.

- Tracker control usability issues due to loss of focus. Fixed.

- Realm Editor added.

- Addressed tickets can be requested as in Leash

All modules:

- removed grayed out UI components that are not being backed
  by current functionality.

- new icons

- support for 64-bit Windows builds under Visual Studio 8

- proper versioning for language resources

ticket: new

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17712 dc483132-0cff-0310-8789-dd5450dbe970

115 files changed:
src/windows/identity/ChangeLog
src/windows/identity/Makefile
src/windows/identity/apiversion.txt
src/windows/identity/config/Makefile
src/windows/identity/config/Makefile.w32
src/windows/identity/config/netidmgr_intver.h.in
src/windows/identity/config/netidmgr_version.h.in
src/windows/identity/help/Makefile
src/windows/identity/help/html/concept_identity.htm
src/windows/identity/help/html/welcome.htm
src/windows/identity/help/popups_password.txt [new file with mode: 0644]
src/windows/identity/include/khmsgtypes.h
src/windows/identity/kconfig/api.c
src/windows/identity/kconfig/kconfig.h
src/windows/identity/kcreddb/attrib.c
src/windows/identity/kcreddb/credential.c
src/windows/identity/kcreddb/credset.c
src/windows/identity/kcreddb/identity.c
src/windows/identity/kcreddb/kcreddb.h
src/windows/identity/kcreddb/type.c
src/windows/identity/kherr/kherr.c
src/windows/identity/kherr/kherr.h
src/windows/identity/kmm/kmm.h
src/windows/identity/kmm/kmm_module.c
src/windows/identity/kmm/kmm_plugin.c
src/windows/identity/kmm/kmm_reg.c
src/windows/identity/kmm/kmm_registrar.c
src/windows/identity/kmm/kmminternal.h
src/windows/identity/kmm/kmmmain.c
src/windows/identity/kmm/lang/kmm_msgs.mc
src/windows/identity/kmq/consumer.c
src/windows/identity/kmq/init.c
src/windows/identity/kmq/kmq.h
src/windows/identity/nidmgrdll/Makefile
src/windows/identity/plugins/common/dynimport.c
src/windows/identity/plugins/krb4/Makefile
src/windows/identity/plugins/krb4/krb4funcs.c
src/windows/identity/plugins/krb4/krb4funcs.h
src/windows/identity/plugins/krb4/krb4main.c
src/windows/identity/plugins/krb4/krb4newcreds.c
src/windows/identity/plugins/krb4/krb4plugin.c
src/windows/identity/plugins/krb4/krbcred.h
src/windows/identity/plugins/krb4/lang/en_us/langres.rc
src/windows/identity/plugins/krb4/lang/krb4_msgs.mc [new file with mode: 0644]
src/windows/identity/plugins/krb4/langres.h
src/windows/identity/plugins/krb4/version.rc
src/windows/identity/plugins/krb5/Makefile
src/windows/identity/plugins/krb5/datarep.c
src/windows/identity/plugins/krb5/datarep.h
src/windows/identity/plugins/krb5/krb5configdlg.c
src/windows/identity/plugins/krb5/krb5configid.c
src/windows/identity/plugins/krb5/krb5funcs.c
src/windows/identity/plugins/krb5/krb5funcs.h
src/windows/identity/plugins/krb5/krb5identpro.c
src/windows/identity/plugins/krb5/krb5main.c
src/windows/identity/plugins/krb5/krb5newcreds.c
src/windows/identity/plugins/krb5/krb5plugin.c
src/windows/identity/plugins/krb5/krbconfig.csv
src/windows/identity/plugins/krb5/krbcred.h
src/windows/identity/plugins/krb5/lang/en_us/langres.rc
src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
src/windows/identity/plugins/krb5/langres.h
src/windows/identity/plugins/krb5/version.rc
src/windows/identity/ui/Makefile
src/windows/identity/ui/appglobal.h
src/windows/identity/ui/cfg_general_wnd.c
src/windows/identity/ui/cfg_identities_wnd.c
src/windows/identity/ui/cfg_notif_wnd.c
src/windows/identity/ui/cfg_plugins_wnd.c
src/windows/identity/ui/configwnd.c
src/windows/identity/ui/configwnd.h
src/windows/identity/ui/credfuncs.c
src/windows/identity/ui/credfuncs.h
src/windows/identity/ui/credwnd.c
src/windows/identity/ui/credwnd.h
src/windows/identity/ui/debugfuncs.c [new file with mode: 0644]
src/windows/identity/ui/debugfuncs.h [new file with mode: 0644]
src/windows/identity/ui/images/app_notify_none.ico
src/windows/identity/ui/images/cfg_plugin.ico
src/windows/identity/ui/images/cfg_plugin_dis.ico [new file with mode: 0644]
src/windows/identity/ui/images/cfg_plugin_err.ico [new file with mode: 0644]
src/windows/identity/ui/images/tk-delete.bmp
src/windows/identity/ui/images/tk-sm.bmp
src/windows/identity/ui/khmapp.h
src/windows/identity/ui/lang/en_us/khapp.rc
src/windows/identity/ui/main.c
src/windows/identity/ui/mainmenu.c
src/windows/identity/ui/mainwnd.c
src/windows/identity/ui/mainwnd.h
src/windows/identity/ui/netidmgr.manifest.amd64.vc7 [new file with mode: 0644]
src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug [new file with mode: 0644]
src/windows/identity/ui/netidmgr.manifest.amd64.vc8 [new file with mode: 0644]
src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug [new file with mode: 0644]
src/windows/identity/ui/newcredwnd.c
src/windows/identity/ui/notifier.c
src/windows/identity/ui/reqdaemon.c
src/windows/identity/ui/resource.h
src/windows/identity/ui/timer.c
src/windows/identity/ui/uiconfig.csv
src/windows/identity/uilib/accel.csv
src/windows/identity/uilib/acceldef.cfg
src/windows/identity/uilib/action.c
src/windows/identity/uilib/actiondef.cfg
src/windows/identity/uilib/actions.csv
src/windows/identity/uilib/alert.c
src/windows/identity/uilib/configui.c
src/windows/identity/uilib/creddlg.c
src/windows/identity/uilib/khaction.h
src/windows/identity/uilib/khactiondef.h
src/windows/identity/uilib/khalerts.h
src/windows/identity/uilib/khconfigui.h
src/windows/identity/uilib/khnewcred.h
src/windows/identity/uilib/khversion.h [new file with mode: 0644]
src/windows/identity/uilib/trackerwnd.c
src/windows/identity/util/perfstat.c

index ada18d2834c58650603563fb41c9234dd2bca4ff..f18508a353eea5e9cdf08864e7838fce0be6f81a 100644 (file)
@@ -1,3 +1,127 @@
+2006-03-07  Jeffrey Altman <jaltman@mit.edu>\r
+\r
+nidmgr32.dll (1.0.2.1)\r
+\r
+- Attempting to obtain new credentials for a principal name that\r
+  contains numbers may result in a 'Identity not specified'\r
+  error. Fixed.\r
+\r
+- If an invalid identity name was specified, an 'Identity not\r
+  specified' error is reported without specifying that the cause was\r
+  an invalid name.  Fixed: reports proper error.\r
+\r
+- Identity names were being validated at the application layer before\r
+  being sent to the identity provider.  This may cause valid names to\r
+  be marked as invalid if the identity provider and the application\r
+  disagree on what a valid name is.  Fixed: identity name validation\r
+  is solely a function of the identity provider.\r
+\r
+- Canonicalizing an identity name that contained certain characters\r
+  failed due to a validation error.  Fixed.\r
+\r
+- Possible deadlock in the new credentials dialog.  (If one plugin\r
+  tries to synchronize custom prompter values from the plugin thread,\r
+  while the UI thread tries to obtain a lock on the new credentials\r
+  data, a deadlock occurs.) Fixed.\r
+\r
+- State information for configuration panels may persist between two\r
+  invocations of the configuration window.  Fixed to clean up state\r
+  information properly.\r
+\r
+- The UI library now has full support for custom actions and custom\r
+  menus.\r
+\r
+- When there are queued alerts and a normal alert is shown, a 'next\r
+  alert...' button appears in the alert which lets the user view the\r
+  next queued alert.  However, if the alert which is displayed\r
+  requires the user to select a command button, selecting the 'next'\r
+  button would be the equivalent of cancelling out of the alert and\r
+  viewing the next one.  The library was updated to not show the\r
+  'next' button if the alert requires user interaction.\r
+\r
+- Credential renewal on half-lifes is now supported as a configurable\r
+  option.\r
+\r
+- Destroying all credentials on exiting netidmgr is a configurable\r
+  option.\r
+\r
+- Debug logging to a file has been added\r
+\r
+netidmgr.exe (1.0.2.1)\r
+\r
+- Selecting 'Ok' in the configuration window didn't notify all the\r
+  configuration panels to apply the changes.  Fixed.\r
+\r
+- PgUp / PgDn / Shift+PgUp / Shift+PgDn keys now work as expected.\r
+\r
+- Root level configuration nodes in the Options dialog now also appear\r
+  on the Options menu.  Configuration nodes that are registered at the\r
+  root level are automatically added to the menu.\r
+\r
+- The UI now has full support for custom actions and custom menus.\r
+\r
+- The UI does not automatically add submenus for actions which are\r
+  associated with menus unless the declaration specifies that it\r
+  should be rendered as a submenu.\r
+\r
+- When displaying alerts, the first button of the alert is always made\r
+  the default.\r
+\r
+- 'Change summary' button in the configuration dialog was removed,\r
+  since it was unused and unnecessary.\r
+\r
+- Ticket icons are displayed in the status column for all credentials.\r
+  Clicking an icon opens the properties dialog for that credential.\r
+\r
+- The UI now has View by Type functionality\r
+\r
+- The UI now has Column selection and reorganization.  The choice\r
+  of columns and their order are preserved between restarts.\r
+\r
+- Handle multiple copies of NetIDMgr.exe being started with different\r
+  version numbers.  Higher version number wins.\r
+\r
+krb4cred.dll (1.0.2.1)\r
+\r
+- During new credentials acquisition, under some circumstances, the\r
+  Kerberos 4 plugin would not notify NetIDMgr about the state of the\r
+  Kerberos 4 ticket acquisition.  This results in other plugins (such\r
+  as AFS) which are depending on the feedback to fail.  Fixed.\r
+\r
+krb5cred.dll (1.0.2.1)\r
+\r
+- If no password is entered while obtaining new credentials, a new TGT\r
+  will not be obtained, but the new credentials operation will not\r
+  fail if there already is a TGT.  Added check to see if the TGT is\r
+  expired and fail the operation if no valid TGT is found.\r
+\r
+- The identity provider can set the Krb5 CCName property for an\r
+  identity incorrectly if there is more than one credential cache\r
+  containing tickets for the same principal.  Fixed.\r
+\r
+- When enumerating ccaches, krb5_cc_resolve was being called with the\r
+  name of the ccache without a type prefix.  Fixed.\r
+\r
+- Tracker control usability issues due to loss of focus. Fixed.\r
+\r
+- Realm Editor added.\r
+\r
+- Addressed tickets can be requested as in Leash\r
+\r
+\r
+All modules:\r
+\r
+- removed grayed out UI components that are not being backed\r
+  by current functionality.\r
+\r
+- new icons\r
+\r
+- support for 64-bit Windows builds under Visual Studio 8\r
+\r
+- proper versioning for language resources\r
+\r
+\r
+\r
 2005-11-29  Jeffrey Altman <jaltman@mit.edu>\r
 \r
 Second Beta of KFW 3.0.0:\r
index 253d7193538c2c06b8f5688ce1915eaf6b9a4115..078e7cb2f91d6590706e3f85a01208b19a219ba4 100644 (file)
@@ -33,7 +33,13 @@ MODULE=all
 !ifndef CLEANRUN\r
 !ifndef TESTRUN\r
 !ifndef ETAGRUN\r
+\r
+# Define KH_NO_WX if the build should not fail on warnings.  The\r
+# default is to treat warnings as errors.\r
+\r
+#RMAKE=$(MAKECMD) /nologo all KH_NO_WX=1\r
 RMAKE=$(MAKECMD) /nologo all\r
+\r
 !else\r
 RMAKE=$(MAKECMD) /nologo etag\r
 !endif\r
index e2367db2a84bb21e31543eda710363ac3456a6f5..008510fba06e4d1c75e53df6f7a9fa007c33742d 100644 (file)
@@ -52,6 +52,83 @@ AppVersion=0.1.2.0
 Date=Nov 30, 2005\r
 # Alpha 2 release of NetIDMgr, along with KFW 3.0.0 beta 2\r
 \r
+#----------------------------------------------------------------\r
 Version=4\r
 AppVersion=1.0.0.0\r
 Date=Dec 05, 2005\r
+# Released with KfW 3.0.0\r
+\r
+#----------------------------------------------------------------\r
+Version=5\r
+AppVersion=1.1.0.0\r
+Date=(TBD)\r
+# Released with KFW 3.1.0\r
+\r
++khui_alert_show_modal(),KMSG_ALERT_SHOW_MODAL, KHUI_ALERT_FLAG_MODAL\r
+# Support for modal alert boxes\r
+\r
++KHUI_PACTION_YES, KHUI_PACTION_NO, KHUI_PACTION_YESALL, KHUI_PACTION_NOALL, KHUI_PACTION_KEEP, KHUI_PACTION_REMOVE, KHUI_PACTION_DISCARD\r
+# Additional pseudo actions\r
+\r
+!tag_khui_action, khui_action\r
+# Membership extension for supporting custom actions.  Type changes\r
+# from 'int' to khm_int32.\r
+\r
++khui_action_create(), khui_action_get_data(), khui_action_delete()\r
+# Support for creating custom actions\r
+\r
+!kmq_msg_subscription, tag_kmq_msg_subscription\r
+# Add 'magic' field.\r
+\r
++KHUI_MENU_NONE\r
+# New identifier for unspecified menu commands.\r
+\r
++khui_menu_insert_action(), khui_menu_get_action(), khui_menu_get_size(), khui_menu_remove_action()\r
+# Functions for manipulating custom menus\r
+\r
++khui_menu_insert_paction()\r
+# Exported, but not exposed as an API.  For inserting actions by\r
+# reference in to menus.\r
+\r
+-khui_menu_add_action(), khui_menu_add_paction()\r
+# Removed deprecated functions.  Temporarily provided as macros. The\r
+# replacements are khui_menu_insert_action() and\r
+# khui_menu_insert_paction() respectively.\r
+\r
++kmq_create_hwnd_subscription()\r
+# Ad-hoc subscriptions can now be obtained for Win32 windows.\r
+\r
+-khui_create_gloabl_accel_table()\r
+# Exported but no longer exposed.\r
+\r
+-khui_action_list_length()\r
+# Exported but no longer exposed.\r
+\r
++kmm_enable_plugin()\r
+# New API for enabling or disabling plugins\r
+\r
+!kmm_plugin_info\r
+# Added 'flags' field.\r
+\r
++KCDB_ATTR_FLAG_TRANSIENT\r
+# New flag for transient attributes.\r
+\r
++kherr_get_prev_event(), kherr_get_last_event()\r
+# For more efficient traversal of the event lists for use by error context handlers.\r
+\r
++KHERR_RF_COMMIT\r
+# Flag for error events to signal that the error event has been committed.\r
+\r
++khui_action_trigger()\r
+\r
++khui_action_set_hwnd()\r
+\r
++KEPT_PTR\r
+\r
++_cptr\r
+\r
+!khc_open_space\r
+# name parameter is now a const string\r
+\r
+!KCDB_ATTRNAME_ISSUE\r
+# Fixed typo
\ No newline at end of file
index f10928fc59831c4c4e5b3a697e280b63ead8f429..5e242824bcad93bfa5eb038d1c18a196154f8963 100644 (file)
@@ -25,7 +25,7 @@
 MODULE=config\r
 !include <Makefile.w32>\r
 \r
-all: showvars mkalldirs mkversion\r
+all: showvars showvers mkalldirs mkversion\r
 \r
 showvars:\r
        $(ECHO) SRC= $(SRC)\r
@@ -36,6 +36,18 @@ showvars:
        $(ECHO) DOXYGEN = $(DOXYGEN)\r
        $(ECHO) HHC = $(HHC)\r
 \r
+showvers:\r
+       $(ECHO) ---- Version Information ----\r
+       $(ECHO) NETIDMGR_VERSION=    $(NETIDMGR_VERSION)\r
+       $(ECHO) NETIDMGR_VERSION_API=$(NETIDMGR_VERSION_API)\r
+       $(ECHO) NETIDMGR_RELEASEDESC=$(NETIDMGR_RELEASEDESC)\r
+       $(ECHO) Build Type          :$(KH_BUILD), $(KH_RELEASE)\r
+       $(ECHO) Strings:\r
+       $(ECHO) Company    = $(NETIDMGR_SRC_COMPANY_1033)\r
+       $(ECHO) Copyright  = $(NETIDMGR_SRC_COPYRIGHT_1033)\r
+       $(ECHO) ---- End Version Information ---\r
+       $(ECHO).\r
+\r
 mkalldirs:\r
 !      if !exist($(DESTROOT))\r
        -$(MKDIR) $(DESTROOT)\r
index 264d19ed28128f48b13f14277feba4e98f32bc1f..5d8026420076cc831f80dd24e733f2c14da20204 100644 (file)
@@ -45,7 +45,7 @@ KHIMAIRA_WIN32_CONFIG=1
 \r
 # Version info\r
 NETIDMGR_VERSION_MAJOR=1\r
-NETIDMGR_VERSION_MINOR=0\r
+NETIDMGR_VERSION_MINOR=1\r
 NETIDMGR_VERSION_PATCH=0\r
 NETIDMGR_VERSION_AUX=0\r
 NETIDMGR_RELEASEDESC=\r
@@ -57,7 +57,12 @@ NETIDMGR_RELEASEDESC=
 #\r
 # Changes to the API version numbers should be documented in\r
 # apiversion.txt at the root of the source tree.\r
-NETIDMGR_VERSION_API=4\r
+NETIDMGR_VERSION_API=5\r
+\r
+# Minimum backwards compatible version.  API versions from\r
+# NETIDMGR_VERSION_API_MINCOMPAT through NETIDMGR_VERSION_API\r
+# inclusive, are compatible with this version.\r
+NETIDMGR_VERSION_API_MINCOMPAT=5\r
 \r
 NETIDMGR_VERSION=$(NETIDMGR_VERSION_MAJOR).$(NETIDMGR_VERSION_MINOR).$(NETIDMGR_VERSION_PATCH).$(NETIDMGR_VERSION_AUX)\r
 NETIDMGR_VERSIONC=$(NETIDMGR_VERSION_MAJOR),$(NETIDMGR_VERSION_MINOR),$(NETIDMGR_VERSION_PATCH),$(NETIDMGR_VERSION_AUX)\r
@@ -153,7 +158,7 @@ RM=del /q
 MKDIR=mkdir\r
 RMDIR=rmdir\r
 ECHO=echo\r
-MAKECMD=nmake\r
+MAKECMD=nmake /nologo\r
 CP=copy /y\r
 LINK=link\r
 CCSV=perl $(SRC)\config\ccsv.pl\r
@@ -272,6 +277,4 @@ etag::
 \r
 .SUFFIXES: .h\r
 \r
-.SILENT:\r
-\r
 !endif\r
index d1863c4334d6267ed4d77972dc93f888768d0c5d..15d47217f93e235942d17b8a89c478f6d2058ddc 100644 (file)
@@ -1,4 +1,4 @@
-$(VERSIONINT): Makefile\r
+$(VERSIONINT): Makefile Makefile.w32\r
        $(CP) << $(VERSIONINT)\r
 /*\r
  * This is an autogenerated file.  Do not modify directly.\r
@@ -30,5 +30,18 @@ $(VERSIONINT): Makefile
 #define KH_VERSTR_BUILDINFO_1033 KH_VERSTR_SPECIAL_1033\r
 !endif\r
 #endif\r
+\r
+#define KH_BUILD "$(KH_BUILD)"\r
+\r
+! if "$(KH_BUILD)"=="RETAIL"\r
+#define KH_BUILD_RETAIL\r
+! elseif "$(KH_RELEASE)"=="PRERELEASE"\r
+#define KH_BUILD_PRERELEASE\r
+! elseif "$(KH_RELEASE)"=="PRIVATE"\r
+#define KH_BUILD_PRIVATE\r
+! elseif "$(KH_RELEASE)"=="SPECIAL"\r
+#define KH_BUILD_SPECIAL\r
+! endif\r
+\r
 <<\r
 \r
index 2be3943a5a09269aca5e1abfc5245b17e5d116be..be53060d00d0643c1a4ae67d939ad1a98b36ee33 100644 (file)
@@ -1,4 +1,4 @@
-$(VERSIONEXT): Makefile\r
+$(VERSIONEXT): Makefile Makefile.w32\r
        $(CP) << $(VERSIONEXT)\r
 /* Copyright (c) 2004 Massachusetts Institute of Technology\r
  *\r
@@ -36,6 +36,7 @@ $(VERSIONEXT): Makefile
 #define KH_VERSION_AUX                 $(NETIDMGR_VERSION_AUX)\r
 \r
 #define KH_VERSION_API          $(NETIDMGR_VERSION_API)\r
+#define KH_VERSION_API_MINCOMPAT $(NETIDMGR_VERSION_API_MINCOMPAT)\r
 \r
 #define KH_VERSION_LIST        $(NETIDMGR_VERSIONC)\r
 #define KH_VERSION_STRING      "$(NETIDMGR_VERSION)"\r
index c45a83f80ada7dee25382db592127109c527a5d2..752ffc996ffc62a0a52fbc84c5731af5e4ba1972 100644 (file)
@@ -32,5 +32,5 @@ INCFILES=$(INCDIR)\khhelp.h
 all: mkdirs $(CHMFILE) $(INCFILES)\r
 \r
 $(CHMFILE): netidmgr.hhp\r
-       -hhc netidmgr.hhp\r
+       -$(HHC) netidmgr.hhp\r
        $(CP) netidmgr.chm $(CHMFILE)\r
index 5e39963da075ddd8f9d3b853f4159e63c693c83d..50802d95b5bb2cbba1dfab807f66c59377012ff4 100644 (file)
@@ -1,11 +1,16 @@
 <html>\r
 <head>\r
-  <title>title</title>\r
-  <meta name="description" content="">\r
-  <meta name="keywords" content="">\r
+  <title>Concepts: Identity</title>\r
+  <meta name="description" content="Concepts: Identity">\r
+  <meta name="keywords" content="identity,concepts">\r
   <link rel="stylesheet" type="text/css" href="nidmgr.css">\r
 </head>\r
 <body>\r
 \r
+<h1>Concepts: Identity</h1>\r
+\r
+<p>\r
+</p>\r
+\r
 </body>\r
 </html>
\ No newline at end of file
index 7423b848d28688c149b7a25ab6150da9dbc7107f..b7d545ba6cdb18fcb372ab5b856f087ea29804c2 100644 (file)
@@ -54,6 +54,12 @@ included in the Kerberos for Windows SDK, which itself is a part of
 the Kerberos for Windows distribution.\r
 </p>\r
 \r
+<p>\r
+We highly recommend interested developers to contact the <a\r
+href="mailto:netidmgr@secure-endpoints.com">netidmgr@secure-endpoints.com</a>\r
+mailing list.\r
+</p>\r
+\r
 <h3>External links</h3>\r
 \r
 <ul>\r
diff --git a/src/windows/identity/help/popups_password.txt b/src/windows/identity/help/popups_password.txt
new file mode 100644 (file)
index 0000000..3958325
--- /dev/null
@@ -0,0 +1,19 @@
+.topic IDH_NC_TABMAIN\r
+Switches to the identity selection panel.\r
+\r
+.topic IDH_NC_TABBUTTON\r
+Switches to the options pangel for this credential type.\r
+\r
+.topic IDH_NC_OK\r
+Change the password for the selected identity.\r
+\r
+.topic IDH_NC_CANCEL\r
+Cancel the change password operation.\r
+\r
+.topic IDH_NC_OPTIONS\r
+Expand the dialog and make the option pages visible for the credential\r
+types for which you will be changing the password for.\r
+\r
+.topic IDH_NC_CREDWND\r
+A brief overview of the credential types and the identities for which\r
+the password will be changed.\r
index c2237ca19163e50bf707da0d607fe1751784b8cd..b590e056bbf8d0b7a6dbe863663f9eb7e75ed667 100644 (file)
@@ -85,7 +85,8 @@
 \r
 /*! \brief Action list messages\r
 \r
-    Notifications of changes in action state.\r
+    Notifications of changes in action state and firing of custom\r
+    actions.\r
 \r
     \see \ref kmq_msg_act\r
  */\r
     \see \ref pi_pt_cred_init\r
  */\r
 #define KMSG_SYSTEM_INIT    1\r
+\r
 /*! \brief Generic uninitialization message\r
 \r
     Used by specific components to signal that the recipient should\r
     khui_enable_actions() or khui_enable_action() and indicates that\r
     one or more actions have changed their state.\r
  */\r
-#define KMSG_ACT_ENABLE 1\r
+#define KMSG_ACT_ENABLE     1\r
 \r
 /*! \brief One or more actions changed check state\r
 \r
     khui_check_action() and indicates that one or more actions have\r
     either been checked or unchecked.\r
  */\r
-#define KMSG_ACT_CHECK 2\r
+#define KMSG_ACT_CHECK      2\r
 \r
 /*! \brief Refresh action states\r
 \r
     Sent after a batch of modifications were made to action states.\r
  */\r
-#define KMSG_ACT_REFRESH 3\r
+#define KMSG_ACT_REFRESH    3\r
+\r
+/*! \brief A new action was created\r
+\r
+    Sent when a new custom action was created.  The \a uparam\r
+    parameter of the message contains the identifier of the newly\r
+    created action.\r
+*/\r
+#define KMSG_ACT_NEW        4\r
+\r
+/*! \brief A custom action was deleted\r
+\r
+    Sent after a custom action is deleted.  The \a uparam parameter of\r
+    the message contains the identifier of the deleted action.\r
+ */\r
+#define KMSG_ACT_DELETE     5\r
+\r
+/*! \brief A custom action has been activated\r
+\r
+    When a custom action is activated, then the listener of that\r
+    custom action receives this message.  Note that only the listener\r
+    for that custom action will receive this notification.\r
+\r
+    \a uparam of the message is set to the identifier of the custom\r
+    action.\r
+ */\r
+#define KMSG_ACT_ACTIVATE   6\r
 \r
+/*! \brief Internal */\r
 #define KMSG_ACT_BEGIN_CMDLINE 128\r
 \r
+/*! \brief Internal */\r
 #define KMSG_ACT_CONTINUE_CMDLINE 129\r
 \r
+/*! \brief Internal */\r
+#define KMSG_ACT_SYNC_CFG 130\r
+\r
 /*@}*/\r
 \r
 /*! \defgroup kmq_msg_cred KMSG_CRED subtypes\r
     respective credentials.\r
 \r
     \note May be sent to individual credential subscriptions.\r
-*/\r
+ */\r
 #define KMSG_CRED_REFRESH   2\r
 \r
 /*! \brief Change the password\r
 \r
 /*! \brief Dialog setup\r
 \r
-    Once KMSG_CRED_NEW_CREDS has been responded to by all the\r
+    Once ::KMSG_CRED_NEW_CREDS has been responded to by all the\r
     credential types, the UI creates the dialog windows using the data\r
     supplied in the ::khui_new_creds_by_type structures and issues\r
     this message.  Each credentials provider is expected to respond by\r
 /*! \brief Dialog pre-start\r
 \r
     Sent after all the credentials providers have responded to\r
-    KMSG_CRED_DIALOG_SETUP and all the initialization has been\r
+    ::KMSG_CRED_DIALOG_SETUP and all the initialization has been\r
     completed.  Credentials providers are expected to respond to this\r
     message by loading any default data into the dialog controls for\r
     each credential type.\r
     processing.\r
 \r
     If the \a result field in the structure is set to\r
-    KHUI_NC_RESULT_GET_CREDS, then new credentials should be obtained\r
-    using the given data.\r
+    ::KHUI_NC_RESULT_PROCESS, then new credentials should be\r
+    obtained using the given data.\r
 \r
     Set the \a response field in the structure to indicate how the UI\r
     should proceed from here.\r
  */\r
 #define KMSG_ALERT_CHECK_QUEUE 4\r
 \r
+/*! \brief Show a modal alert\r
+\r
+    Message parameters:\r
+    - \b vparam : held pointer to a ::khui_alert object.\r
+\r
+    \note the ::khui_alert object will be released when the queued\r
+        messages are displayed.\r
+ */\r
+#define KMSG_ALERT_SHOW_MODAL 5\r
+\r
 /*@}*/\r
 \r
 /*! \defgroup kmq_msg_ident KMSG_IDENT Subtypes\r
         name to be validated will be in the \a name_src member.  The\r
         buffer will be NULL terminated with a maximum limit of\r
         KCDB_IDENT_MAXCCH_NAME characters including the terminating\r
-        NULL.\r
+        NULL, consisting only of characters in KCDB_IDENT_VALID_CHARS\r
         The \a result member should be set to one of the following\r
         depending on the result of the validation:\r
 \r
index 30e5f488fb1d19b4f35115658507d672bc4e9859..72a20acbcc7fec788348625416ce0cb20c690e69 100644 (file)
@@ -313,6 +313,47 @@ khcint_RegOpenKeyEx(HKEY hkey, LPCWSTR sSubKey, DWORD ulOptions,
     return rv;\r
 }\r
 \r
+LONG\r
+khcint_RegDeleteKey(HKEY hKey,\r
+                    LPCWSTR lpSubKey) {\r
+    int i;\r
+    wchar_t sk_name[KCONF_MAXCCH_NAME];\r
+    FILETIME ft;\r
+    size_t cch;\r
+    LONG rv = ERROR_SUCCESS;\r
+\r
+    /* go through and find the case sensitive match for the key */\r
+\r
+    if (FAILED(StringCchLength(lpSubKey, KCONF_MAXCCH_NAME, &cch)))\r
+        return ERROR_BADKEY;\r
+\r
+    for (i=0; ;i++) {\r
+        LONG l;\r
+        DWORD dw;\r
+\r
+        dw = ARRAYLENGTH(sk_name);\r
+        l = RegEnumKeyEx(hKey, i, sk_name, &dw,\r
+                         NULL, NULL, NULL, &ft);\r
+\r
+        if (l != ERROR_SUCCESS) {\r
+            rv = ERROR_BADKEY;\r
+            goto _cleanup;\r
+        }\r
+\r
+        if (!(wcsncmp(sk_name, lpSubKey, cch))) {\r
+            /* bingo! ?? */\r
+            if ((sk_name[cch] == L'\0' ||\r
+                 sk_name[cch] == L'~')) {\r
+                rv = RegDeleteKey(hKey, sk_name);\r
+                goto _cleanup;\r
+            }\r
+        }\r
+    }\r
+\r
+ _cleanup:\r
+    return rv;\r
+}\r
+\r
 LONG\r
 khcint_RegCreateKeyEx(HKEY hKey,\r
                       LPCWSTR lpSubKey,\r
@@ -533,14 +574,10 @@ khcint_space_open_key(kconf_conf_space * s, khm_int32 flags) {
         }\r
         if(!hk && (flags & KHM_FLAG_CREATE)) {\r
             khcint_RegCreateKeyEx(HKEY_CURRENT_USER, \r
-                                  s->regpath, \r
-                                  0,\r
-                                  NULL,\r
+                                  s->regpath, 0, NULL,\r
                                   REG_OPTION_NON_VOLATILE,\r
                                   KEY_READ | KEY_WRITE,\r
-                                  NULL,\r
-                                  &hk,\r
-                                  &disp);\r
+                                  NULL, &hk, &disp);\r
         }\r
         if(hk) {\r
             EnterCriticalSection(&cs_conf_global);\r
@@ -632,7 +669,7 @@ khcint_free_space(kconf_conf_space * r) {
 \r
 khm_int32 \r
 khcint_open_space_int(kconf_conf_space * parent, \r
-                      wchar_t * sname, size_t n_sname, \r
+                      const wchar_t * sname, size_t n_sname, \r
                       khm_int32 flags, kconf_conf_space **result) {\r
     kconf_conf_space * p;\r
     kconf_conf_space * c;\r
@@ -735,13 +772,13 @@ khcint_open_space_int(kconf_conf_space * parent,
 }\r
 \r
 KHMEXP khm_int32 KHMAPI \r
-khc_open_space(khm_handle parent, wchar_t * cspace, khm_int32 flags, \r
+khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, \r
                khm_handle * result) {\r
     kconf_handle * h;\r
     kconf_conf_space * p;\r
     kconf_conf_space * c = NULL;\r
     size_t cbsize;\r
-    wchar_t * str;\r
+    const wchar_t * str;\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
 \r
     if(!khc_is_config_running()) {\r
@@ -781,7 +818,7 @@ khc_open_space(khm_handle parent, wchar_t * cspace, khm_int32 flags,
 \r
     str = cspace;\r
     while(TRUE) {\r
-        wchar_t * end = NULL;\r
+        const wchar_t * end = NULL;\r
 \r
         if (!(flags & KCONF_FLAG_NOPARSENAME)) {\r
 \r
@@ -1788,16 +1825,17 @@ khc_value_exists(khm_handle conf, wchar_t * value) {
 \r
     c = khc_space_from_handle(conf);\r
 \r
-    if(!khc_is_machine_handle(conf))\r
+    if (khc_is_user_handle(conf))\r
         hku = khcint_space_open_key(c, KHM_PERM_READ);\r
-    hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);\r
+    if (khc_is_machine_handle(conf))\r
+        hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE);\r
 \r
     if(hku && (RegQueryValueEx(hku, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))\r
         rv |= KCONF_FLAG_USER;\r
     if(hkm && (RegQueryValueEx(hkm, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS))\r
         rv |= KCONF_FLAG_MACHINE;\r
 \r
-    if(c->schema) {\r
+    if(c->schema && khc_is_schema_handle(conf)) {\r
         for(i=0; i<c->nSchema; i++) {\r
             if(!wcscmp(c->schema[i].name, value)) {\r
                 rv |= KCONF_FLAG_SCHEMA;\r
@@ -1856,14 +1894,26 @@ khc_remove_value(khm_handle conf, wchar_t * value, khm_int32 flags) {
     return rv;\r
 }\r
 \r
+/* called with cs_conf_global held */\r
 khm_int32\r
 khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {\r
     kconf_conf_space * cc;\r
     kconf_conf_space * cn;\r
+    kconf_conf_space * p;\r
 \r
     /* TODO: if this is the last child space and the parent is marked\r
        for deletion, delete the parent as well. */\r
 \r
+    p = TPARENT(c);\r
+\r
+    /* We don't allow deleting top level keys.  They are\r
+       predefined. */\r
+#ifdef DEBUG\r
+    assert(p);\r
+#endif\r
+    if (!p)\r
+        return KHM_ERROR_INVALID_OPERATION;\r
+            \r
     cc = TFIRSTCHILD(c);\r
     while (cc) {\r
         cn = LNEXT(cc);\r
@@ -1874,40 +1924,38 @@ khcint_remove_space(kconf_conf_space * c, khm_int32 flags) {
     }\r
 \r
     cc = TFIRSTCHILD(c);\r
-    if (!cc) {\r
-        kconf_conf_space * p;\r
-\r
-        if (c->refcount) {\r
-            c->flags |= (flags &\r
-                         (KCONF_SPACE_FLAG_DELETE_M |\r
-                          KCONF_SPACE_FLAG_DELETE_U));\r
-        } else {\r
-            p = TPARENT(c);\r
-            \r
-            TDELCHILD(p, c);\r
-\r
-            if (c->regpath) {\r
-                if (flags & KCONF_SPACE_FLAG_DELETE_U)\r
-                    RegDeleteKey(HKEY_CURRENT_USER,\r
-                                 c->regpath);\r
-                if (flags & KCONF_SPACE_FLAG_DELETE_M)\r
-                    RegDeleteKey(HKEY_LOCAL_MACHINE,\r
-                                 c->regpath);\r
-            }\r
-\r
-            khcint_free_space(c);\r
-        }\r
+    if (!cc && c->refcount == 0) {\r
+        TDELCHILD(p, c);\r
+        khcint_free_space(c);\r
     } else {\r
         c->flags |= (flags &\r
                      (KCONF_SPACE_FLAG_DELETE_M |\r
                       KCONF_SPACE_FLAG_DELETE_U));\r
     }\r
 \r
+    if (c->regpath && p->regpath) {\r
+        HKEY hk;\r
+\r
+        if (flags & KCONF_SPACE_FLAG_DELETE_U) {\r
+            hk = khcint_space_open_key(p, KCONF_FLAG_USER);\r
+\r
+            if (hk)\r
+                khcint_RegDeleteKey(hk, c->name);\r
+        }\r
+        if (flags & KCONF_SPACE_FLAG_DELETE_M) {\r
+            hk = khcint_space_open_key(p, KCONF_FLAG_MACHINE);\r
+\r
+            if (hk)\r
+                khcint_RegDeleteKey(hk, c->name);\r
+        }\r
+    }\r
+\r
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
 KHMEXP khm_int32 KHMAPI\r
 khc_remove_space(khm_handle conf) {\r
+\r
     /*\r
        - mark this space as well as all child spaces as\r
          'delete-on-close' using flags.  Mark should indicate which\r
index 4e9a49e9bebebd096fbf1c9ec7f9a25613822548..5ec65f703c20c7703c7008893d957410d9d98597 100644 (file)
@@ -42,7 +42,7 @@
 \r
     \see kconf_load_schema()\r
 */\r
-typedef struct kconf_schema_t {\r
+typedef struct tag_kconf_schema {\r
     wchar_t *   name;       /*!< name of the object being described.\r
                                 Optional for KC_ENDSPACE type object,\r
                                 but required for everything else.\r
@@ -63,7 +63,7 @@ typedef struct kconf_schema_t {
                                 not support defining a default value\r
                                 here. */\r
     wchar_t *   description;/*!< a friendly description of the value\r
-                                or configuration space */\r
+                                or configuration space. */\r
 } kconf_schema;\r
 \r
 /*! \name Configuration data types\r
@@ -153,12 +153,12 @@ typedef struct kconf_schema_t {
     By default, the configuration space name,\r
 \r
     \code\r
-    L"foo/bar"\r
+    L"foo\\bar"\r
     \endcode\r
 \r
     is taken to mean the configuration space \a bar which is a\r
     subspace of \a foo.  If ::KCONF_FLAG_NOPARSENAME is set, then this\r
-    is taken to mean configuration space \a foo/bar.\r
+    is taken to mean configuration space \a foo\\bar.\r
  */\r
 #define KCONF_FLAG_NOPARSENAME   0x00000040\r
 \r
@@ -229,7 +229,7 @@ typedef struct kconf_schema_t {
 \r
 */\r
 KHMEXP khm_int32 KHMAPI \r
-khc_open_space(khm_handle parent, wchar_t * cspace, khm_int32 flags, \r
+khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, \r
                khm_handle * result);\r
 \r
 /*! \brief Set the shadow space for a configuration handle\r
index f77ebccf1a44f912d7a18734fedcc29058bd3a82..4e9d7bf341cc51f6037f6a74ad5bd79cd34f4beb 100644 (file)
@@ -173,13 +173,22 @@ kcdb_attr_sys_cb(khm_handle vcred,
                 *((FILETIME *) buf) = IntToFt(_I64_MAX);\r
             } else {\r
                 FILETIME ftc;\r
+                khm_int64 i_re;\r
+                khm_int64 i_ct;\r
 \r
                 GetSystemTimeAsFileTime(&ftc);\r
 \r
-                *((FILETIME *) buf) =\r
-                    IntToFt(FtToInt(((FILETIME *)\r
-                                     kcdb_cred_buf_get(c,KCDB_ATTR_RENEW_EXPIRE))\r
-                                    - FtToInt(&ftc)));\r
+                i_re = FtToInt(((FILETIME *)\r
+                                kcdb_cred_buf_get(c, KCDB_ATTR_RENEW_EXPIRE)));\r
+                i_ct = FtToInt(&ftc);\r
+\r
+                if (i_re > i_ct)\r
+                    *((FILETIME *) buf) =\r
+                        IntToFt(i_re - i_ct);\r
+                else\r
+                    *((FILETIME *) buf) =\r
+                        IntToFt(0);\r
+\r
                 *pcb_buf = sizeof(FILETIME);\r
             }\r
 \r
@@ -329,7 +338,7 @@ kcdb_attrib_init(void)
     LoadString(hinst_kcreddb, IDS_PARENT, sbuf, ARRAYLENGTH(sbuf));\r
     attrib.short_desc = sbuf;\r
     attrib.long_desc = NULL;\r
-    attrib.flags = KCDB_ATTR_FLAG_SYSTEM;\r
+    attrib.flags = KCDB_ATTR_FLAG_SYSTEM | KCDB_ATTR_FLAG_HIDDEN;\r
     attrib.compute_cb = NULL;\r
     attrib.compute_min_cbsize = 0;\r
     attrib.compute_max_cbsize = 0;\r
@@ -392,8 +401,8 @@ kcdb_attrib_init(void)
         KCDB_ATTR_FLAG_ALTVIEW |\r
         KCDB_ATTR_FLAG_VOLATILE;\r
     attrib.compute_cb = kcdb_attr_sys_cb;\r
-    attrib.compute_min_cbsize = sizeof(__int64);\r
-    attrib.compute_max_cbsize = sizeof(__int64);\r
+    attrib.compute_min_cbsize = sizeof(FILETIME);\r
+    attrib.compute_max_cbsize = sizeof(FILETIME);\r
 \r
     kcdb_attrib_register(&attrib, NULL);\r
 \r
@@ -411,8 +420,8 @@ kcdb_attrib_init(void)
         KCDB_ATTR_FLAG_ALTVIEW |\r
         KCDB_ATTR_FLAG_VOLATILE;\r
     attrib.compute_cb = kcdb_attr_sys_cb;\r
-    attrib.compute_min_cbsize = sizeof(__int64);\r
-    attrib.compute_max_cbsize = sizeof(__int64);\r
+    attrib.compute_min_cbsize = sizeof(FILETIME);\r
+    attrib.compute_max_cbsize = sizeof(FILETIME);\r
 \r
     kcdb_attrib_register(&attrib, NULL);\r
 \r
index 37f246534da4cfb5cc0b2d4534e94fa1da24afc0..6886cc5b6c0516b9e2d2df5fb43cbf881b7cfc8c 100644 (file)
@@ -156,10 +156,23 @@ KHMEXP khm_int32 KHMAPI kcdb_cred_update(khm_handle vdest,
             kcdb_buf_set_value(&dest->buf, i, i, srcbuf, cbsrcbuf);\r
             rv = KHM_ERROR_SUCCESS;\r
 \r
-_skip_copy:\r
+       _skip_copy:\r
             kcdb_attrib_release_info(a);\r
             kcdb_type_release_info(t);\r
-        }\r
+        } else {\r
+           if (KHM_FAILED(kcdb_attrib_get_info(i, &a)))\r
+               continue;\r
+\r
+           if (!(a->flags & KCDB_ATTR_FLAG_COMPUTED) &&\r
+               (a->flags & KCDB_ATTR_FLAG_TRANSIENT) &&\r
+               kcdb_cred_val_exist(dest, i)) {\r
+               kcdb_buf_set_value(&dest->buf, i, i, NULL, 0);\r
+\r
+               rv = KHM_ERROR_SUCCESS;\r
+           }\r
+\r
+           kcdb_attrib_release_info(a);\r
+       }\r
     }\r
 \r
     if (dest->flags != src->flags) {\r
@@ -174,7 +187,7 @@ _skip_copy:
             rv = KHM_ERROR_SUCCESS;\r
     }\r
 \r
-_exit:\r
+ _exit:\r
     kcdb_cred_unlock_write();\r
     return rv;\r
 }\r
index 9be551ba1f28c77392bd806a09cbfa80b563d1e5..dda9817d3af14e80d870dc49ff0f979ba72caf62 100644 (file)
@@ -31,7 +31,8 @@ CRITICAL_SECTION cs_credset;
 kcdb_credset * kcdb_credsets = NULL;\r
 kcdb_credset * kcdb_root_credset = NULL;\r
 \r
-void kcdb_credset_init(void)\r
+void \r
+kcdb_credset_init(void)\r
 {\r
     khm_handle rc;\r
 \r
@@ -43,14 +44,16 @@ void kcdb_credset_init(void)
     kcdb_root_credset->flags |= KCDB_CREDSET_FLAG_ROOT;\r
 }\r
 \r
-void kcdb_credset_exit(void)\r
+void \r
+kcdb_credset_exit(void)\r
 {\r
     /*TODO: free the credsets */\r
     DeleteCriticalSection(&cs_credset);\r
 }\r
 \r
 /* called on an unreleased credset, or with credset::cs held */\r
-void kcdb_credset_buf_new(kcdb_credset * cs)\r
+void \r
+kcdb_credset_buf_new(kcdb_credset * cs)\r
 {\r
     cs->clist = PMALLOC(KCDB_CREDSET_INITIAL_SIZE * \r
                         sizeof(kcdb_credset_credref));\r
@@ -62,14 +65,16 @@ void kcdb_credset_buf_new(kcdb_credset * cs)
 }\r
 \r
 /* called on an unreleased credset, or with credset::cs held */\r
-void kcdb_credset_buf_delete(kcdb_credset * cs)\r
+void \r
+kcdb_credset_buf_delete(kcdb_credset * cs)\r
 {\r
     PFREE(cs->clist);\r
     cs->nc_clist = 0;\r
     cs->nclist = 0;\r
 }\r
 \r
-void kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist)\r
+void \r
+kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist)\r
 {\r
     if(cs->nc_clist < nclist) {\r
         kcdb_credset_credref * new_clist;\r
@@ -89,7 +94,8 @@ void kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist)
     }\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_create(khm_handle * result)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_create(khm_handle * result)\r
 {\r
     kcdb_credset * cs;\r
 \r
@@ -112,7 +118,8 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_create(khm_handle * result)
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_delete(khm_handle vcredset)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_delete(khm_handle vcredset)\r
 {\r
     kcdb_credset * cs;\r
     int i;\r
@@ -227,12 +234,12 @@ kcdb_credset_collect_core(kcdb_credset * cs1,
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_collect(\r
-    khm_handle cs_dest,\r
-    khm_handle cs_src, \r
-    khm_handle identity, \r
-    khm_int32 type,\r
-    khm_int32 * delta)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_collect(khm_handle cs_dest,\r
+                    khm_handle cs_src, \r
+                    khm_handle identity, \r
+                    khm_int32 type,\r
+                    khm_int32 * delta)\r
 {\r
     kcdb_credset * cs;\r
     kcdb_credset * rcs;\r
@@ -317,12 +324,12 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_collect(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_collect_filtered(\r
-    khm_handle cs_dest,\r
-    khm_handle cs_src,\r
-    kcdb_cred_filter_func filter,\r
-    void * rock,\r
-    khm_int32 * delta)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_collect_filtered(khm_handle cs_dest,\r
+                             khm_handle cs_src,\r
+                             kcdb_cred_filter_func filter,\r
+                             void * rock,\r
+                             khm_int32 * delta)\r
 {\r
     kcdb_credset * cs;\r
     kcdb_credset * rcs;\r
@@ -418,7 +425,8 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_collect_filtered(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_flush(khm_handle vcredset)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_flush(khm_handle vcredset)\r
 {\r
     int i;\r
     kcdb_credset * cs;\r
@@ -448,11 +456,11 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_flush(khm_handle vcredset)
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_extract(\r
-    khm_handle destcredset, \r
-    khm_handle sourcecredset, \r
-    khm_handle identity, \r
-    khm_int32 type)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_extract(khm_handle destcredset, \r
+                    khm_handle sourcecredset, \r
+                    khm_handle identity, \r
+                    khm_int32 type)\r
 {\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
     kcdb_credset * dest;\r
@@ -500,7 +508,7 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_extract(
         c = src->clist[i].cred;\r
         if(kcdb_cred_is_active_cred((khm_handle) c) &&\r
             (!identity || c->identity == identity) &&\r
-            (type==KCDB_TYPE_INVALID || c->type == type))\r
+            (type < 0 || c->type == type))\r
         {\r
             if(isRoot) {\r
                 khm_handle newcred;\r
@@ -527,11 +535,11 @@ _exit:
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_extract_filtered(\r
-    khm_handle destcredset,\r
-    khm_handle sourcecredset,\r
-    kcdb_cred_filter_func filter,\r
-    void * rock)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_extract_filtered(khm_handle destcredset,\r
+                             khm_handle sourcecredset,\r
+                             kcdb_cred_filter_func filter,\r
+                             void * rock)\r
 {\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
     kcdb_credset * dest;\r
@@ -607,7 +615,9 @@ _exit:
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f, void * rock)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f,\r
+                  void * rock)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
@@ -648,10 +658,10 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_
     return rv;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_get_cred(\r
-    khm_handle vcredset,\r
-    khm_int32 idx,\r
-    khm_handle * cred)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_get_cred(khm_handle vcredset,\r
+                     khm_int32 idx,\r
+                     khm_handle * cred)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
@@ -681,13 +691,13 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_get_cred(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_find_filtered(\r
-    khm_handle credset,\r
-    khm_int32 idx_start,\r
-    kcdb_cred_filter_func f,\r
-    void * rock,\r
-    khm_handle * cred,\r
-    khm_int32 * idx)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_find_filtered(khm_handle credset,\r
+                          khm_int32 idx_start,\r
+                          kcdb_cred_filter_func f,\r
+                          void * rock,\r
+                          khm_handle * cred,\r
+                          khm_int32 * idx)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
@@ -782,9 +792,9 @@ kcdb_credset_find_cred(khm_handle vcredset,
     }\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_del_cred(\r
-    khm_handle vcredset,\r
-    khm_int32 idx)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_del_cred(khm_handle vcredset,\r
+                     khm_int32 idx)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
@@ -825,9 +835,9 @@ _exit:
     return code;\r
 }\r
 \r
-khm_int32 kcdb_credset_update_cred_ref(\r
-    khm_handle credset,\r
-    khm_handle cred)\r
+khm_int32 \r
+kcdb_credset_update_cred_ref(khm_handle credset,\r
+                            khm_handle cred)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
@@ -855,9 +865,9 @@ khm_int32 kcdb_credset_update_cred_ref(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_del_cred_ref(\r
-    khm_handle credset,\r
-    khm_handle cred)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_del_cred_ref(khm_handle credset,\r
+                         khm_handle cred)\r
 {\r
     kcdb_credset * cs;\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
@@ -888,10 +898,10 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_del_cred_ref(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_add_cred(\r
-    khm_handle credset,\r
-    khm_handle cred,\r
-    khm_int32 idx)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_add_cred(khm_handle credset,\r
+                     khm_handle cred,\r
+                     khm_int32 idx)\r
 {\r
     int new_idx;\r
     kcdb_credset * cs;\r
@@ -930,9 +940,9 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_add_cred(
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_get_size(\r
-    khm_handle credset,\r
-    khm_size * size)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_get_size(khm_handle credset,\r
+                     khm_size * size)\r
 {\r
     kcdb_credset * cs;\r
 \r
@@ -957,7 +967,8 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_get_size(
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_purge(khm_handle credset)\r
+KHMEXP khm_int32 KHMAPI\r
+kcdb_credset_purge(khm_handle credset)\r
 {\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
     kcdb_credset * cs;\r
@@ -1037,7 +1048,8 @@ kcdb_credset_unseal(khm_handle credset) {
 \r
 \r
 /* wrapper for qsort and also parameter gobbling FSM. */\r
-int __cdecl kcdb_creds_comp_wrapper(const void * a, const void * b)\r
+int __cdecl \r
+kcdb_creds_comp_wrapper(const void * a, const void * b)\r
 {\r
     static void * rock = NULL;\r
     static kcdb_cred_comp_func comp = NULL;\r
@@ -1057,10 +1069,10 @@ int __cdecl kcdb_creds_comp_wrapper(const void * a, const void * b)
                 rock);\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_credset_sort(\r
-    khm_handle credset,\r
-    kcdb_cred_comp_func comp,\r
-    void * rock)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_credset_sort(khm_handle credset,\r
+                 kcdb_cred_comp_func comp,\r
+                 void * rock)\r
 {\r
     khm_int32 code = KHM_ERROR_SUCCESS;\r
     kcdb_credset * cs;\r
@@ -1082,16 +1094,17 @@ KHMEXP khm_int32 KHMAPI kcdb_credset_sort(
     kcdb_creds_comp_wrapper(rock, NULL);\r
     kcdb_creds_comp_wrapper(NULL, (void *) comp);\r
 \r
-    qsort(cs->clist, cs->nclist, sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper);\r
+    qsort(cs->clist, cs->nclist,\r
+         sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper);\r
 \r
     LeaveCriticalSection(&(cs->cs));\r
     return code;\r
 }\r
 \r
-KHMEXP khm_int32 KHMAPI kcdb_cred_comp_generic(\r
-    khm_handle cred1, \r
-    khm_handle cred2, \r
-    void * rock)\r
+KHMEXP khm_int32 KHMAPI \r
+kcdb_cred_comp_generic(khm_handle cred1, \r
+                      khm_handle cred2, \r
+                      void * rock)\r
 {\r
     kcdb_cred_comp_order * o = (kcdb_cred_comp_order *) rock;\r
     int i;\r
index e96c996081bfd76dcfdac1dba852fb0a65488b81..b9b8194b1b87d3b79fa0674c1519d4bdcfba2e01 100644 (file)
@@ -1146,6 +1146,13 @@ kcdb_identpro_validate_name(const wchar_t * name)
        before calling the identity provider */\r
     if(FAILED(StringCchLength(name, KCDB_IDENT_MAXCCH_NAME, &cch)))\r
         return KHM_ERROR_TOO_LONG;\r
+\r
+    /* We can't really make an assumption about the valid characters\r
+       in an identity.  So we let the identity provider decide */\r
+#ifdef VALIDATE_IDENTIY_CHARACTERS\r
+    if(wcsspn(name, KCDB_IDENT_VALID_CHARS) != cch)\r
+        return KHM_ERROR_INVALID_NAME;\r
+#endif\r
     \r
     EnterCriticalSection(&cs_ident);\r
     if(kcdb_ident_sub != NULL) {\r
@@ -1204,8 +1211,7 @@ kcdb_identpro_validate_identity(khm_handle identity)
 }\r
 \r
 KHMEXP khm_int32 KHMAPI \r
-kcdb_identpro_canon_name(\r
-                         const wchar_t * name_in, \r
+kcdb_identpro_canon_name(const wchar_t * name_in, \r
                          wchar_t * name_out, \r
                          khm_size * cb_name_out)\r
 {\r
@@ -1237,8 +1243,7 @@ kcdb_identpro_canon_name(
         namex.cb_name_dest = sizeof(name_tmp);\r
         namex.result = KHM_ERROR_NOT_IMPLEMENTED;\r
 \r
-        rv = kmq_send_sub_msg(\r
-                              sub,\r
+        rv = kmq_send_sub_msg(sub,\r
                               KMSG_IDENT,\r
                               KMSG_IDENT_CANON_NAME,\r
                               0,\r
@@ -1273,8 +1278,7 @@ kcdb_identpro_canon_name(
 }\r
 \r
 KHMEXP khm_int32 KHMAPI \r
-kcdb_identpro_compare_name(\r
-                           const wchar_t * name1,\r
+kcdb_identpro_compare_name(const wchar_t * name1,\r
                            const wchar_t * name2)\r
 {\r
     khm_handle sub;\r
index 52ca980ef5a7843f5c41dabd8510fc66af850661..7826a82c0d3a6a4657cf323b5d6ea8d9c6757c5e 100644 (file)
@@ -99,6 +99,9 @@ Functions, macros etc. for manipulating identities.
            name */\r
 #define KCDB_IDENT_MAXCB_NAME (sizeof(wchar_t) * KCDB_IDENT_MAXCCH_NAME)\r
 \r
+/*! \brief Valid characters in an identity name */\r
+#define KCDB_IDENT_VALID_CHARS L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._@-/"\r
+\r
 /*!\r
 \name Flags for identities */\r
 /*@{*/\r
@@ -1104,7 +1107,7 @@ kcdb_credset_flush(khm_handle credset);
         set.  If set to NULL, matches all identities.\r
 \r
     \param[in] type The credential type to match in the source credential set.\r
-        If set to KCDB_TYPE_INVALID, matches all types.\r
+        If set to KCDB_CREDTYPE_INVALID, matches all types.\r
 \r
     \note This function does not check for duplicate credentials.\r
 \r
@@ -1926,8 +1929,9 @@ kcdb_creds_is_equal(khm_handle cred1,
 \r
 /********************************************************************/\r
 \r
-/*! \defgroup kcdb_type Credential attribute types */\r
-/*@{*/\r
+/*! \defgroup kcdb_type Credential attribute types\r
+\r
+@{*/\r
 \r
 /*! \brief Convert a field to a string\r
 \r
@@ -2217,13 +2221,24 @@ kcdb_type_get_id(wchar_t *name, khm_int32 * id);
         info parameter is NULL, the function returns KHM_ERROR_SUCCESS\r
         if \a id is a valid type id, and returns KHM_ERROR_NOT_FOUND\r
         otherwise.\r
+\r
+    \see kcdb_type_release_info()\r
 */\r
 KHMEXP khm_int32 KHMAPI \r
 kcdb_type_get_info(khm_int32 id, kcdb_type ** info);\r
 \r
+/*! \brief Release a reference to a type info structure\r
+\r
+    Releases the reference to the type information obtained with a\r
+    prior call to kcdb_type_get_info().\r
+ */\r
 KHMEXP khm_int32 KHMAPI \r
 kcdb_type_release_info(kcdb_type * info);\r
 \r
+/*! \brief Get the name of a type\r
+\r
+    Retrieves the non-localized name of the specified type.\r
+ */\r
 KHMEXP khm_int32 KHMAPI \r
 kcdb_type_get_name(khm_int32 id, \r
                    wchar_t * buffer, \r
@@ -2659,6 +2674,16 @@ kcdb_attrib_get_ids(khm_int32 and_flags,
     required.\r
  */\r
 #define KCDB_ATTR_FLAG_ALTVIEW  0x00000200\r
+\r
+/*! \brief Transient attribute\r
+\r
+    A transient attribute is one whose absence is meaningful.  When\r
+    updating one record using another, if a transient attribute is\r
+    absent in the source but present in the destination, then the\r
+    attribute is removed from the destination.\r
+*/\r
+#define KCDB_ATTR_FLAG_TRANSIENT 0x00000400\r
+\r
 /*@}*/\r
 \r
 /*! \defgroup kcdb_credattr_idnames Standard attribute IDs and names */\r
@@ -2803,7 +2828,7 @@ kcdb_attrib_get_ids(khm_int32 and_flags,
 #define KCDB_ATTRNAME_FLAGS         L"Flags"\r
 \r
 #define KCDB_ATTRNAME_PARENT_NAME   L"Parent"\r
-#define KCDB_ATTRNAME_ISSUE         L"Issed"\r
+#define KCDB_ATTRNAME_ISSUE         L"Issued"\r
 #define KCDB_ATTRNAME_EXPIRE        L"Expires"\r
 #define KCDB_ATTRNAME_RENEW_EXPIRE  L"RenewExpires"\r
 #define KCDB_ATTRNAME_TIMELEFT      L"TimeLeft"\r
index 3df10482c6520b89a61d7a4ef825c0e8cdf4e9bd..30771c07a31796437d20a2ccb8e89bbf44a10240 100644 (file)
@@ -212,7 +212,7 @@ khm_int32 KHMAPI kcdb_type_date_toString(
     GetLocalTime(&st_now);\r
     FileTimeToSystemTime(ft, &st_d);\r
     SystemTimeToTzSpecificLocalTime(NULL, &st_d, &st_dl);\r
-    if(st_now.wYear == st_dl.wYear &&\r
+    if (st_now.wYear == st_dl.wYear &&\r
         st_now.wMonth == st_dl.wMonth &&\r
         st_now.wDay == st_dl.wDay)\r
         today = 1;\r
@@ -227,7 +227,6 @@ khm_int32 KHMAPI kcdb_type_date_toString(
             NULL,\r
             NULL,\r
             0) * sizeof(wchar_t);\r
-        cbsize += sizeof(wchar_t);\r
     }\r
 \r
     cbsize += GetTimeFormat(\r
@@ -238,8 +237,6 @@ khm_int32 KHMAPI kcdb_type_date_toString(
         NULL,\r
         0) * sizeof(wchar_t);\r
 \r
-    cbsize += sizeof(wchar_t);\r
-\r
     if(!buffer || *cb_buf < cbsize) {\r
         *cb_buf = cbsize;\r
         return KHM_ERROR_TOO_LONG;\r
@@ -374,7 +371,11 @@ FtIntervalToString(LPFILETIME data, wchar_t * buffer, khm_size * cb_buf)
     d = s / (3600*24);\r
 \r
     if(ift == _I64_MAX) {\r
+#ifdef INDICATE_UNKNOWN_EXPIRY_TIMES\r
         LoadString(hinst_kcreddb, IDS_IVL_UNKNOWN, ibuf, sizeof(ibuf)/sizeof(wchar_t));\r
+#else\r
+        StringCbCopy(ibuf, sizeof(ibuf), L"");\r
+#endif\r
     } else if(s < 0) {\r
         LoadString(hinst_kcreddb, IDS_IVL_EXPIRED, ibuf, sizeof(ibuf)/sizeof(wchar_t));\r
     } else if(d > 0) {\r
index d8b145d240b034d055c47b68d04ca9ca80e913f2..3b7a5d453f15884bfcd375a993d2c3a1640f70a8 100644 (file)
@@ -59,6 +59,8 @@ KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
                                          khm_int32 filter,\r
                                          kherr_serial serial) {\r
 \r
+    khm_size idx;\r
+\r
     assert(h);\r
 \r
     EnterCriticalSection(&cs_error);\r
@@ -86,9 +88,21 @@ KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
             KHERR_CTX_END |\r
             KHERR_CTX_ERROR;\r
 \r
-    ctx_handlers[n_ctx_handlers].h = h;\r
-    ctx_handlers[n_ctx_handlers].filter = filter;\r
-    ctx_handlers[n_ctx_handlers].serial = serial;\r
+    /* Since commit events are the most frequent, we put those\r
+       handlers at the top of the list.  When dispatching a commit\r
+       event, we stop looking at the list when we find a filter that\r
+       doesn't filter for commit events. */\r
+    if (filter & KHERR_CTX_EVTCOMMIT) {\r
+       idx = 0;\r
+       memmove(&ctx_handlers[1], &ctx_handlers[0],\r
+               n_ctx_handlers * sizeof(ctx_handlers[0]));\r
+    } else {\r
+       idx = n_ctx_handlers;\r
+    }\r
+\r
+    ctx_handlers[idx].h = h;\r
+    ctx_handlers[idx].filter = filter;\r
+    ctx_handlers[idx].serial = serial;\r
 \r
     n_ctx_handlers++;\r
 \r
@@ -139,7 +153,14 @@ void notify_ctx_event(enum kherr_ctx_event e, kherr_context * c) {
                 if (h != ctx_handlers[i].h)\r
                     i--;\r
             }\r
-        }\r
+        } else if (e == KHERR_CTX_EVTCOMMIT &&\r
+                  !(ctx_handlers[i].filter & KHERR_CTX_EVTCOMMIT)) {\r
+           /* All handlers that filter for commit events are at the\r
+              top of the list.  If this handler wasn't filtering for\r
+              it, then there's no point in goint further down the\r
+              list. */\r
+           break;\r
+       }\r
     }\r
 }\r
 \r
@@ -384,7 +405,15 @@ void free_context(kherr_context * c) {
 \r
 void add_event(kherr_context * c, kherr_event * e)\r
 {\r
+    kherr_event * te;\r
+\r
     EnterCriticalSection(&cs_error);\r
+    te = QBOTTOM(c);\r
+    if (te && !(te->flags & KHERR_RF_COMMIT)) {\r
+       notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);\r
+       te->flags |= KHERR_RF_COMMIT;\r
+    }\r
+\r
     QPUT(c,e);\r
     if(c->severity >= e->severity) {\r
         if (e->severity <= KHERR_ERROR)\r
@@ -436,7 +465,8 @@ static void arg_from_param(DWORD_PTR ** parm, kherr_param p) {
         if (t == KEPT_INT32 ||\r
             t == KEPT_UINT32 ||\r
             t == KEPT_STRINGC ||\r
-            t == KEPT_STRINGT) {\r
+            t == KEPT_STRINGT ||\r
+            t == KEPT_PTR) {\r
 \r
             *(*parm)++ = (DWORD_PTR) parm_data(p);\r
 \r
@@ -648,6 +678,9 @@ void resolve_event_strings(kherr_event * e)
 \r
 \r
 KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e) {\r
+    if (!e)\r
+        return;\r
+\r
     EnterCriticalSection(&cs_error);\r
     resolve_event_strings(e);\r
     LeaveCriticalSection(&cs_error);\r
@@ -673,7 +706,7 @@ KHMEXP void KHMAPI kherr_evaluate_last_event(void) {
 \r
     resolve_event_strings(e);\r
 \r
-_exit:\r
+ _exit:\r
     LeaveCriticalSection(&cs_error);\r
 }\r
 \r
@@ -1051,6 +1084,12 @@ KHMEXP void KHMAPI kherr_release_context(kherr_context * c) {
         kherr_event * e;\r
         kherr_context * p;\r
 \r
+       e = QBOTTOM(c);\r
+       if (e && !(e->flags & KHERR_RF_COMMIT)) {\r
+           notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);\r
+           e->flags |= KHERR_RF_COMMIT;\r
+       }\r
+\r
         notify_ctx_event(KHERR_CTX_END, c);\r
 \r
         p = TPARENT(c);\r
@@ -1172,6 +1211,26 @@ KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e)
     return ee;\r
 }\r
 \r
+KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e)\r
+{\r
+    kherr_event * ee;\r
+\r
+    EnterCriticalSection(&cs_error);\r
+    ee = QPREV(e);\r
+    LeaveCriticalSection(&cs_error);\r
+\r
+    return ee;\r
+}\r
+\r
+KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c)\r
+{\r
+    kherr_event * e;\r
+    EnterCriticalSection(&cs_error);\r
+    e = QBOTTOM(c);\r
+    LeaveCriticalSection(&cs_error);\r
+    return e;\r
+}\r
+\r
 KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c)\r
 {\r
     kherr_context * cc;\r
index 6ae943e4ecffa8eade9f2c674af345431ce5476b..99e7856220bc5e7ea2cd5ec41ddc272e45163602 100644 (file)
@@ -97,8 +97,9 @@ enum kherr_parm_types {
   KEPT_INT64,\r
   KEPT_UINT64,\r
   KEPT_STRINGC,                 /*!< String constant */\r
-  KEPT_STRINGT                  /*!< String.  Will be freed using\r
+  KEPT_STRINGT,                 /*!< String.  Will be freed using\r
                                      free() when the event is freed */\r
+  KEPT_PTR                      /*!< Pointer type. */\r
 };\r
 \r
 #ifdef _WIN32\r
@@ -114,16 +115,25 @@ typedef khm_ui_8 kherr_param;
 enum tag_kherr_severity {\r
   KHERR_FATAL = 0,              /*!< Fatal error.*/\r
   KHERR_ERROR,                  /*!< Non-fatal error.  We'll probably\r
-                                survive.  See the suggested action. */\r
+                                 survive.  See the suggested action. */\r
   KHERR_WARNING,                /*!< Warning. Something almost broke\r
-                                 or soon will.  See the suggested\r
-                                 action. */\r
+                                 or soon will.  See the suggested\r
+                                 action. */\r
   KHERR_INFO,                   /*!< Informational. Something happened\r
                                   that we would like you to know\r
                                   about. */\r
-  KHERR_DEBUG_3 = 64,           /*!< Verbose debug level 3 (high) */\r
-  KHERR_DEBUG_2 = 65,           /*!< Verbose debug level 2 (medium) */\r
-  KHERR_DEBUG_1 = 66,           /*!< Verbose debug level 1 (low) */\r
+  KHERR_DEBUG_1 = 64,           /*!< Verbose debug level 1 (high)\r
+                                 Events at this severity level are\r
+                                 not required to be based on\r
+                                 localized strings. */\r
+  KHERR_DEBUG_2 = 65,           /*!< Verbose debug level 2 (medium)\r
+                                 Events at this severity level are\r
+                                 not required to be based on\r
+                                 localized strings. */\r
+  KHERR_DEBUG_3 = 66,           /*!< Verbose debug level 3 (low)\r
+                                 Events at this severity level are\r
+                                 not required to be based on\r
+                                 localized strings. */\r
   KHERR_RESERVED_BANK = 127,    /*!< Internal use */\r
   KHERR_NONE = 128              /*!< Nothing interesting has happened\r
                                   so far */\r
@@ -255,10 +265,14 @@ enum kherr_event_flags {
                                 /*!< The event is a representation of\r
                                   a folded context. */\r
 \r
-    KHERR_RF_INERT          = 0x00040000\r
+    KHERR_RF_INERT          = 0x00040000,\r
                                 /*!< Inert event.  The event has\r
                                   already been dealt with and is no\r
                                   longer considered significant. */\r
+    KHERR_RF_COMMIT         = 0x00080000\r
+                               /*!< Committed event.  The commit\r
+                                 handlers for this event have already\r
+                                 been called. */\r
 };\r
 \r
 /*! \brief Serial number for error contexts */\r
@@ -284,7 +298,7 @@ typedef struct tag_kherr_context {
                                   context object. */\r
 \r
     kherr_severity severity;    \r
-                                /*!< Severity level.  One of the\r
+                               /*!< Severity level.  One of the\r
                                  severity levels listed below. This\r
                                  is the severity level of the context\r
                                  and is the maximum severity level of\r
@@ -367,8 +381,10 @@ enum kherr_ctx_event {
     KHERR_CTX_BEGIN  = 0x0001,  /*!< A new context was created */\r
     KHERR_CTX_DESCRIBE=0x0002,  /*!< A context was described */\r
     KHERR_CTX_END    = 0x0004,  /*!< A context was closed */\r
-    KHERR_CTX_ERROR  = 0x0008   /*!< A context switched to an error\r
+    KHERR_CTX_ERROR  = 0x0008,  /*!< A context switched to an error\r
                                   state */\r
+    KHERR_CTX_EVTCOMMIT = 0x0010 /*!< A event was committed into the\r
+                                  context */\r
 };\r
 \r
 /*! \brief Context event handler\r
@@ -428,6 +444,15 @@ typedef void (KHMAPI * kherr_ctx_handler)(enum kherr_ctx_event,
     still intact.  The pointer that is supplied should not be used to\r
     obtain a handle on the context.\r
 \r
+    <b>KHERR_CTX_EVTCOMMIT</b>: An event was committed into the error\r
+    context.  An event is committed when another event is reported\r
+    after the event, or if the context is closed.  Since the last\r
+    event that is reported can still be modified by adding new\r
+    information, the event remains open until it is no longer the last\r
+    event or the context is no longer active.  When this notification\r
+    is received, the last event in the context's event queue is the\r
+    event that was committed.\r
+\r
     \param[in] h Context event handler, of type ::kherr_ctx_handler\r
 \r
     \param[in] filter A combination of ::kherr_ctx_event values\r
@@ -585,6 +610,7 @@ kherr_reportf_ex(enum kherr_severity severity,
 #endif\r
                  const wchar_t * long_desc_fmt,\r
                  ...);\r
+#define _reportf_ex kherr_reportf_ex\r
 \r
 /*! \brief Report a formatted message\r
 \r
@@ -596,6 +622,7 @@ kherr_reportf_ex(enum kherr_severity severity,
 KHMEXP kherr_event * __cdecl\r
 kherr_reportf(const wchar_t * long_desc_fmt,\r
               ...);\r
+#define _reportf kherr_reportf\r
 \r
 /*! \brief Create a parameter out of a transient string\r
 \r
@@ -620,6 +647,7 @@ KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
 #define _uint64(ui) kherr_val(KEPT_UINT64, ui)\r
 #define _cstr(cs)   kherr_val(KEPT_STRINGC, cs)\r
 #define _tstr(ts)   kherr_val(KEPT_STRINGT, ts)\r
+#define _cptr(p)    kherr_val(KEPT_PTR, p)\r
 #define _dupstr(s)  kherr_dup_string(s)\r
 \r
 /* convenience macros for calling kherr_report */\r
@@ -887,9 +915,14 @@ KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c, khm_ui_4 * num, khm_u
     The returned pointer is only valid as long as there is a hold on\r
     \a c.  Once the context is released with a call to\r
     kherr_release_context() all pointers to events in the context\r
-    becomes invalid.\r
+    become invalid.\r
 \r
-    Use kherr_get_next_event() to obtain the other events.\r
+    In addition, the last event in a context may still be "active".  A\r
+    thread can still modify the last event as long as the context is\r
+    active.\r
+\r
+    \see kherr_get_next_event(), kherr_get_prev_event(),\r
+    kherr_get_last_event()\r
  */\r
 KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c);\r
 \r
@@ -903,10 +936,55 @@ KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c);
     The returned pointer is only valid as long as there is a hold on\r
     \a c.  Once the context is released with a call to\r
     kherr_release_context() all pointers to events in the context\r
-    becomes invalid.\r
+    become invalid.\r
+\r
+    In addition, the last event in a context may still be "active".  A\r
+    thread can still modify the last event as long as the context is\r
+    active.\r
+\r
+    \see kherr_get_first_event(), kherr_get_prev_event(),\r
+    kherr_get_last_event()\r
  */\r
 KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e);\r
 \r
+/*! \brief Get the previous event\r
+\r
+    Returns a pointer to the event that was reported in the context\r
+    containing \a e prior to \a e being reported.\r
+\r
+    The returned pointer is only valid as long as there is a hold on\r
+    the error context.  Once the context is released with a call to\r
+    kherr_release_context() all pointers to events in the context\r
+    become invalid.\r
+\r
+    In addition, the last event in a context may still be "active". A\r
+    thread can still modify the last event as long as the context is\r
+    active.\r
+\r
+    \see kherr_get_first_event(), kherr_get_next_event(),\r
+    kherr_get_last_event()\r
+ */\r
+KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e);\r
+\r
+/*! \brief Get the last event in an error context\r
+\r
+    Returns a pointer to the last error event that that was reported\r
+    to the context \a c.\r
+\r
+    The returned pointer is only valid as long as there is a hold on\r
+    the error context.  Once the context is released with a call to\r
+    kherr_release_context(), all pointers to events in the context\r
+    become invalid.\r
+\r
+    In addtion, the last event in a context may still be "active".  A\r
+    thread can still modify the last event as long as the context is\r
+    active.\r
+\r
+    \see kherr_get_first_event(), kherr_get_next_event(),\r
+    kherr_get_prev_event()\r
+ */\r
+KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c);\r
+\r
 /*! \brief Get the first child context of a context\r
 \r
     Contexts are arranged in a hiearchy.  This function returns the\r
index 0dc7e4cea4dcc05d665e79c11a13fb22346c3307..be2981b96c41165a3399711d137e1e401f7f6845 100644 (file)
@@ -146,8 +146,23 @@ typedef struct tag_kmm_plugin_info {
                                     failure */\r
 \r
     kmm_plugin  h_plugin;       /*!< Handle to plugin */\r
+\r
+    khm_int32   flags;          /*!< Flags for the plugin. Currently\r
+                                  this can only specify\r
+                                  ::KMM_PLUGIN_FLAG_DISABLED. */\r
 } kmm_plugin_info;\r
 \r
+/*! \brief The plugin is disabled\r
+\r
+    This flag will be set in the \a flags field of the\r
+    ::kmm_plugin_info structure for a plugin that has been marked as\r
+    disabled.  If the plugin is currently running, but marked as\r
+    disabled for future sessions, then this bit will be set in \a\r
+    flags , but the \a state of the plugin will indicate that the\r
+    plugin is running.\r
+ */\r
+#define KMM_PLUGIN_FLAG_DISABLED    0x0400\r
+\r
 /*! \name Plugin types\r
 @{*/\r
 /*! \brief A credentials provider\r
@@ -178,6 +193,7 @@ typedef struct tag_kmm_plugin_info {
 \r
 /*! \brief Plugin states */\r
 enum _kmm_plugin_states {\r
+    KMM_PLUGIN_STATE_FAIL_INIT = -6,    /*!< Failed to initialize */\r
     KMM_PLUGIN_STATE_FAIL_UNKNOWN = -5, /*!< Failed due to unknown\r
                                           reasons */\r
     KMM_PLUGIN_STATE_FAIL_MAX_FAILURE = -4, /*!< The plugin has\r
@@ -796,6 +812,20 @@ kmm_release_plugin_info_i(kmm_plugin_info * info);
 KHMEXP khm_int32   KHMAPI\r
 kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next);\r
 \r
+/*! \brief Enables or disables a plugin\r
+\r
+    This function currently does not take effect immediately.  However\r
+    it marks the plugin as enabled or disabled so that the next time\r
+    NetIDMgr starts, the module manager will act accordingly.\r
+\r
+    \param[in] p Handle to the plugin\r
+\r
+    \param[in] enable If non-zero, the plugin will be marked as\r
+        enabled.  Otherwise the plugin will be marked as disabled.\r
+ */\r
+KHMEXP khm_int32   KHMAPI\r
+kmm_enable_plugin(kmm_plugin p, khm_boolean enable);\r
+\r
 /*! \brief Register a plugin\r
 \r
     The \a plugin member defines the plugin to be registered.  The \a\r
index d5a61c74016e2516e8d9bfd5ba8c21a37e02b99e..932bdf8ef3d69868b1138563aa127111e657b4ea 100644 (file)
@@ -28,6 +28,9 @@
 #include<netidmgr_version.h>\r
 #include<assert.h>\r
 \r
+/* should only be accessed from the registrar thread */\r
+khm_size kmm_active_modules = 0;\r
+\r
 kmm_module_i * kmmint_get_module_i(wchar_t * name)\r
 {\r
     kmm_module_i * m;\r
@@ -95,9 +98,6 @@ void kmmint_free_module(kmm_module_i * m)
         PFREE(m->version_info);\r
 \r
     PFREE(m);\r
-\r
-    if (kmm_all_modules == NULL)\r
-        SetEvent(evt_exit);\r
 }\r
 \r
 KHMEXP khm_int32   KHMAPI kmm_hold_module(kmm_module module)\r
@@ -114,6 +114,7 @@ KHMEXP khm_int32   KHMAPI kmm_hold_module(kmm_module module)
 KHMEXP khm_int32   KHMAPI kmm_release_module(kmm_module vm)\r
 {\r
     kmm_module_i * m;\r
+\r
     if(!kmm_is_module(vm))\r
         return KHM_ERROR_INVALID_PARAM;\r
 \r
@@ -131,14 +132,16 @@ KHMEXP khm_int32   KHMAPI kmm_release_module(kmm_module vm)
 \r
 khm_int32\r
 kmmint_check_api_version(DWORD v) {\r
-    /* for now, we require an exact match.  In the future when we are\r
-       swamped with so much time that we don't know what to do with\r
-       it, we can actually parse the apiversion.txt file and create a\r
-       compatibility table which we can check against the functions\r
-       used by the module and decide whether or not it is\r
-       compatible. */\r
-\r
-    if (v != KH_VERSION_API)\r
+    /* for now, we allow API versions in the range\r
+       KH_VERSION_API_MINCOMPAT through KH_VERSION_API, inclusive.  In\r
+       the future when we are swamped with so much time that we don't\r
+       know what to do with it, we can actually parse the\r
+       apiversion.txt file and create a compatibility table which we\r
+       can check against the functions used by the module and decide\r
+       whether or not it is compatible. */\r
+\r
+    if (v < KH_VERSION_API_MINCOMPAT ||\r
+        v > KH_VERSION_API)\r
         return KHM_ERROR_INCOMPATIBLE;\r
     else\r
         return KHM_ERROR_SUCCESS;\r
@@ -582,6 +585,9 @@ kmm_get_module_info_i(kmm_module vm, kmm_module_info * info) {
         info->state = m->state;\r
 \r
         info->h_module = vm;\r
+\r
+        info->file_version = m->file_version;\r
+        info->product_version = m->prod_version;\r
         kmm_hold_module(vm);\r
 \r
         rv = KHM_ERROR_SUCCESS;\r
@@ -629,6 +635,7 @@ kmm_load_default_modules(void) {
     if(KHM_FAILED(rv))\r
         return rv;\r
 \r
+    _begin_task(KHERR_CF_TRANSITIVE);\r
     _report_mr0(KHERR_NONE, MSG_LOAD_DEFAULT);\r
     _describe();\r
 \r
@@ -652,6 +659,8 @@ kmm_load_default_modules(void) {
     if(csm)\r
         khc_close_space(csm);\r
 \r
+    _end_task();\r
+\r
     return rv;\r
 }\r
 \r
index b8a90c9fe9e65159d196b5048f873cd42892ce79..665eb6330a1a2429219fbca175a3fffd6ed6044c 100644 (file)
@@ -160,6 +160,52 @@ kmmint_free_plugin(kmm_plugin_i * pi)
     PFREE(pi);\r
 }\r
 \r
+KHMEXP khm_int32   KHMAPI\r
+kmm_enable_plugin(kmm_plugin p, khm_boolean enable) {\r
+    kmm_plugin_i * pi;\r
+    khm_int32 rv = KHM_ERROR_NOT_FOUND; /* default to error */\r
+    khm_handle csp_plugin = NULL;\r
+    khm_int32 flags;\r
+\r
+    EnterCriticalSection(&cs_kmm);\r
+    if (!kmm_is_plugin(p)) {\r
+        rv = KHM_ERROR_INVALID_PARAM;\r
+        goto _cleanup;\r
+    }\r
+\r
+    pi = kmm_plugin_from_handle(p);\r
+\r
+    if (KHM_FAILED(rv = kmm_get_plugin_config(pi->p.name, 0, &csp_plugin))) {\r
+        goto _cleanup;\r
+    }\r
+\r
+    if (KHM_FAILED(rv = khc_read_int32(csp_plugin, L"Flags", &flags))) {\r
+        goto _cleanup;\r
+    }\r
+\r
+    if (enable) {\r
+        flags &= ~KMM_PLUGIN_FLAG_DISABLED;\r
+        pi->flags &= ~KMM_PLUGIN_FLAG_DISABLED;\r
+    } else {\r
+        flags |= KMM_PLUGIN_FLAG_DISABLED;\r
+        pi->flags |= KMM_PLUGIN_FLAG_DISABLED;\r
+    }\r
+\r
+    if (KHM_FAILED(rv = khc_write_int32(csp_plugin, L"Flags", flags))) {\r
+        goto _cleanup;\r
+    }\r
+\r
+    rv = KHM_ERROR_SUCCESS;\r
+\r
+ _cleanup:\r
+    LeaveCriticalSection(&cs_kmm);\r
+\r
+    if (csp_plugin)\r
+        khc_close_space(csp_plugin);\r
+\r
+    return rv;\r
+}\r
+\r
 KHMEXP khm_int32   KHMAPI\r
 kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
@@ -203,8 +249,10 @@ kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {
 \r
     info->state = pi->state;\r
 \r
-    info->h_plugin = p;\r
     kmm_hold_plugin(p);\r
+    info->h_plugin = p;\r
+\r
+    info->flags = (pi->flags & KMM_PLUGIN_FLAG_DISABLED);\r
 \r
  _cleanup:\r
     LeaveCriticalSection(&cs_kmm);\r
@@ -331,7 +379,7 @@ kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
 \r
     p = kmmint_get_plugin_i(plugin->name);\r
 \r
-    /* released below or in kmm_init_module() */\r
+    /* released below or in kmmint_init_module() */\r
     kmm_hold_plugin(kmm_handle_from_plugin(p));\r
 \r
     if(p->state != KMM_PLUGIN_STATE_NONE &&\r
index 131cb7514477cfa09edba764ebc2c8a0488fb264..98b3cdd92df7108d02505781c4f0d5963067a64f 100644 (file)
@@ -281,13 +281,40 @@ _exit:
 KHMEXP khm_int32   KHMAPI \r
 kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags)\r
 {\r
-    /*TODO: implement this */\r
-    return KHM_ERROR_NOT_IMPLEMENTED;\r
+    khm_handle csp_plugin = NULL;\r
+    khm_int32 rv = KHM_ERROR_SUCCESS;\r
+\r
+    rv = kmm_get_plugin_config(plugin, config_flags, &csp_plugin);\r
+\r
+    if (KHM_FAILED(rv))\r
+        goto _cleanup;\r
+\r
+    rv = khc_remove_space(csp_plugin);\r
+\r
+ _cleanup:\r
+\r
+    if (csp_plugin)\r
+        khc_close_space(csp_plugin);\r
+\r
+    return rv;\r
 }\r
 \r
 KHMEXP khm_int32   KHMAPI \r
 kmm_unregister_module(wchar_t * module, khm_int32 config_flags)\r
 {\r
-    /*TODO: implement this */\r
-    return KHM_ERROR_NOT_IMPLEMENTED;\r
+    khm_handle csp_module = NULL;\r
+    khm_int32 rv = KHM_ERROR_SUCCESS;\r
+\r
+    rv = kmm_get_module_config(module, config_flags, &csp_module);\r
+\r
+    if (KHM_FAILED(rv))\r
+        goto _cleanup;\r
+\r
+    rv = khc_remove_space(csp_module);\r
+\r
+ _cleanup:\r
+    if (csp_module)\r
+        khc_close_space(csp_module);\r
+\r
+    return rv;\r
 }\r
index 1e632c7bac619971ba52399d99e7248585d57cd2..73651d44c6f3c9e3815ea93b056d8aa6a42676a0 100644 (file)
@@ -25,6 +25,9 @@
 /* $Id$ */\r
 \r
 #include<kmminternal.h>\r
+#ifdef DEBUG\r
+#include<assert.h>\r
+#endif\r
 \r
 static LONG pending_modules = 0;\r
 static LONG pending_plugins = 0;\r
@@ -88,11 +91,10 @@ kmm_load_pending(void) {
 \r
 /*! \internal\r
   \brief Message handler for the registrar thread. */\r
-khm_boolean KHMAPI kmm_reg_cb(\r
-    khm_int32 msg_type, \r
-    khm_int32 msg_sub_type, \r
-    khm_ui_4 uparam,\r
-    void *vparam)\r
+khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type, \r
+                                 khm_int32 msg_sub_type, \r
+                                 khm_ui_4 uparam,\r
+                                 void *vparam)\r
 {\r
     /* we should only be getting <KMSG_KMM,KMSG_KMM_I_REG> anyway */\r
     if(msg_type != KMSG_KMM || msg_sub_type != KMSG_KMM_I_REG)\r
@@ -100,22 +102,22 @@ khm_boolean KHMAPI kmm_reg_cb(
 \r
     switch(uparam) {\r
         case KMM_REG_INIT_MODULE:\r
-            kmm_init_module((kmm_module_i *) vparam);\r
+            kmmint_init_module((kmm_module_i *) vparam);\r
             kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));\r
             break;\r
 \r
         case KMM_REG_EXIT_MODULE:\r
-            kmm_exit_module((kmm_module_i *) vparam);\r
+            kmmint_exit_module((kmm_module_i *) vparam);\r
             kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam));\r
             break;\r
 \r
         case KMM_REG_INIT_PLUGIN:\r
-            kmm_init_plugin((kmm_plugin_i *) vparam);\r
+            kmmint_init_plugin((kmm_plugin_i *) vparam);\r
             kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));\r
             break;\r
 \r
         case KMM_REG_EXIT_PLUGIN:\r
-            kmm_exit_plugin((kmm_plugin_i *) vparam);\r
+            kmmint_exit_plugin((kmm_plugin_i *) vparam);\r
             kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam));\r
             break;\r
     }\r
@@ -126,15 +128,13 @@ khm_boolean KHMAPI kmm_reg_cb(
   \brief The registrar thread.\r
 \r
   The only thing this function does is to dispatch messages to the\r
-  callback routine ( kmm_reg_cb() ) */\r
-DWORD WINAPI kmm_registrar(\r
-  LPVOID lpParameter\r
-)\r
+  callback routine ( kmmint_reg_cb() ) */\r
+DWORD WINAPI kmmint_registrar(LPVOID lpParameter)\r
 {\r
     tid_registrar = GetCurrentThreadId();\r
 \r
-    kmq_subscribe(KMSG_KMM, kmm_reg_cb);\r
-    kmq_subscribe(KMSG_SYSTEM, kmm_reg_cb);\r
+    kmq_subscribe(KMSG_KMM, kmmint_reg_cb);\r
+    kmq_subscribe(KMSG_SYSTEM, kmmint_reg_cb);\r
 \r
     SetEvent(evt_startup);\r
 \r
@@ -151,11 +151,15 @@ DWORD WINAPI kmm_registrar(
   Each plugin gets its own plugin thread which is used to dispatch\r
   messages to the plugin.  This acts as the thread function for the\r
   plugin thread.*/\r
-DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)\r
+DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter)\r
 {\r
     DWORD rv = 0;\r
     kmm_plugin_i * p = (kmm_plugin_i *) lpParameter;\r
 \r
+    _begin_task(0);\r
+    _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name));\r
+    _describe();\r
+\r
     TlsSetValue(tls_kmm, (LPVOID) p);\r
 \r
     kmm_hold_plugin(kmm_handle_from_plugin(p));\r
@@ -163,16 +167,46 @@ DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)
     p->tid_thread = GetCurrentThreadId();\r
 \r
     if (IsBadCodePtr(p->p.msg_proc)) {\r
+        _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR);\r
         rv = KHM_ERROR_INVALID_PARAM;\r
     } else {\r
-        rv = (p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_INIT, \r
-                            0, (void *) &(p->p)));\r
+        rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT, \r
+                              0, (void *) &(p->p));\r
+        _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv));\r
     }\r
 \r
     /* if it fails to initialize, we exit the plugin */\r
     if(KHM_FAILED(rv)) {\r
+\r
+        kherr_report(KHERR_ERROR,\r
+                     (wchar_t *) MSG_PB_INIT_FAIL_S,\r
+                     (wchar_t *) KHERR_FACILITY,\r
+                     NULL,\r
+                     (wchar_t *) MSG_PB_INIT_FAIL,\r
+                     (wchar_t *) MSG_PB_INIT_FAIL_G,\r
+                     KHERR_FACILITY_ID,\r
+                     KHERR_SUGGEST_NONE,\r
+                     _cstr(p->p.name),\r
+                     _cstr(p->p.description),\r
+                     _cstr(p->module->path),\r
+                     _cstr(p->module->support),\r
+                     KHERR_RF_MSG_SHORT_DESC |\r
+                     KHERR_RF_MSG_LONG_DESC |\r
+                     KHERR_RF_MSG_SUGGEST\r
+#ifdef _WIN32\r
+                     ,KHERR_HMODULE\r
+#endif\r
+                     );\r
+        _resolve();\r
+\r
+        /* exit the plugin first.  Otherwise it may not uninitialize correctly */\r
+        (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));\r
+\r
         kmmint_remove_from_plugin_queue(p);\r
         rv = 1;\r
+        _end_task();\r
+\r
+        p->state = KMM_PLUGIN_STATE_FAIL_INIT;\r
         goto _exit;\r
     }\r
 \r
@@ -196,6 +230,10 @@ DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)
 \r
     p->state = KMM_PLUGIN_STATE_RUNNING;\r
 \r
+    _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE);\r
+\r
+    _end_task();\r
+\r
     /* if there were any plugins that were waiting for this one to\r
        start, we should start them too */\r
     EnterCriticalSection(&cs_kmm);\r
@@ -237,8 +275,9 @@ DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)
 \r
     p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p));\r
 \r
-_exit:\r
-    p->state = KMM_PLUGIN_STATE_EXITED;\r
+ _exit:\r
+    if (p->state >= 0)\r
+        p->state = KMM_PLUGIN_STATE_EXITED;\r
 \r
     /* the following call will automatically release the plugin */\r
     kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, \r
@@ -255,17 +294,17 @@ _exit:
 /*! \internal\r
   \brief Initialize a plugin\r
 \r
-  \note If kmm_init_plugin() is called on a plugin, then kmm_exit_plugin()\r
+  \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin()\r
       \b must be called for the plugin.\r
 \r
   \note Should only be called from the context of the registrar thread */\r
-void kmm_init_plugin(kmm_plugin_i * p) {\r
+void kmmint_init_plugin(kmm_plugin_i * p) {\r
     DWORD dummy;\r
     khm_handle csp_plugin   = NULL;\r
     khm_handle csp_plugins  = NULL;\r
     khm_int32 t;\r
 \r
-    /* the following will be undone in kmm_exit_plugin() */\r
+    /* the following will be undone in kmmint_exit_plugin() */\r
     kmm_hold_plugin(kmm_handle_from_plugin(p));\r
 \r
     EnterCriticalSection(&cs_kmm);\r
@@ -290,6 +329,10 @@ void kmm_init_plugin(kmm_plugin_i * p) {
     }\r
 \r
     p->state = KMM_PLUGIN_STATE_PREINIT;\r
+\r
+    kmmint_delist_plugin(p);\r
+    kmmint_list_plugin(p);\r
+\r
     LeaveCriticalSection(&cs_kmm);\r
 \r
     if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) {\r
@@ -300,7 +343,7 @@ void kmm_init_plugin(kmm_plugin_i * p) {
     }\r
 \r
     if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin)) ||\r
-        KHM_FAILED(khc_read_int32(csp_plugin, L"Flags", &t))) {\r
+       KHM_FAILED(khc_read_int32(csp_plugin, L"Flags", &t))) {\r
         if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) {\r
             _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);\r
 \r
@@ -321,11 +364,11 @@ void kmm_init_plugin(kmm_plugin_i * p) {
             p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED;\r
             goto _exit;\r
         }\r
+\r
     }\r
 \r
     if(t & KMM_PLUGIN_FLAG_DISABLED) {\r
-        _report_mr0(KHERR_ERROR, MSG_IP_DISABLED);\r
-\r
+        p->flags |= KMM_PLUGIN_FLAG_DISABLED;\r
         p->state = KMM_PLUGIN_STATE_FAIL_DISABLED;\r
         goto _exit;\r
     }\r
@@ -400,12 +443,9 @@ void kmm_init_plugin(kmm_plugin_i * p) {
         PFREE(deps);\r
 \r
     } while(FALSE);\r
-    LeaveCriticalSection(&cs_kmm);\r
 \r
-    EnterCriticalSection(&cs_kmm);\r
     p->module->plugin_count++;\r
-    kmmint_delist_plugin(p);\r
-    kmmint_list_plugin(p);\r
+\r
     LeaveCriticalSection(&cs_kmm);\r
 \r
     if(p->state == KMM_PLUGIN_STATE_HOLD) {\r
@@ -418,7 +458,7 @@ void kmm_init_plugin(kmm_plugin_i * p) {
 \r
     p->ht_thread = CreateThread(NULL,\r
                                 0,\r
-                                kmm_plugin_broker,\r
+                                kmmint_plugin_broker,\r
                                 (LPVOID) p,\r
                                 CREATE_SUSPENDED,\r
                                 &dummy);\r
@@ -466,18 +506,20 @@ _exit:
   linked list and hashtable, it also frees up p.\r
    \r
   \note Should only be called from the context of the registrar thread. */\r
-void kmm_exit_plugin(kmm_plugin_i * p) {\r
+void kmmint_exit_plugin(kmm_plugin_i * p) {\r
     int np;\r
+    khm_boolean release_plugin = TRUE;\r
 \r
     if(p->state == KMM_PLUGIN_STATE_RUNNING ||\r
-        p->state == KMM_PLUGIN_STATE_INIT)\r
-    {\r
+       p->state == KMM_PLUGIN_STATE_INIT) {\r
+\r
         kmq_post_thread_quit_message(p->tid_thread, 0, NULL);\r
         /* when we post the quit message to the plugin thread, the plugin\r
            broker terminates the plugin and posts a EXIT_PLUGIN message,\r
            which calls this function again.  We just exit here because\r
            the EXIT_PLUGIN message will end up calling us again momentarily */\r
         return;\r
+\r
     }\r
 \r
     if(p->ht_thread) {\r
@@ -488,16 +530,25 @@ void kmm_exit_plugin(kmm_plugin_i * p) {
 \r
     EnterCriticalSection(&cs_kmm);\r
 \r
-    /* undo reference count done in kmm_init_plugin() */\r
+    /* undo reference count done in kmmint_init_plugin() */\r
     if(p->state == KMM_PLUGIN_STATE_EXITED ||\r
-        p->state == KMM_PLUGIN_STATE_HOLD) \r
-    {\r
+       p->state == KMM_PLUGIN_STATE_HOLD) {\r
+\r
         np = --(p->module->plugin_count);\r
+\r
     } else {\r
         /* the plugin was never active.  We can't base a module unload\r
            decision on np */\r
         np = TRUE;\r
     }\r
+\r
+    /* The plugin is in an error state.  We need to keep the plugin\r
+       record in tact so that the failure information is kept\r
+       around. */\r
+    if (p->state < KMM_PLUGIN_STATE_NONE) {\r
+        release_plugin = FALSE;\r
+    }\r
+\r
     LeaveCriticalSection(&cs_kmm);\r
 \r
     if(!np) {\r
@@ -507,8 +558,9 @@ void kmm_exit_plugin(kmm_plugin_i * p) {
         kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) p->module);\r
     }\r
 \r
-    /* release the hold obtained in kmm_init_plugin() */\r
-    kmm_release_plugin(kmm_handle_from_plugin(p));\r
+    /* release the hold obtained in kmmint_init_plugin() */\r
+    if (release_plugin)\r
+        kmm_release_plugin(kmm_handle_from_plugin(p));\r
 }\r
 \r
 /*! \internal\r
@@ -517,7 +569,7 @@ void kmm_exit_plugin(kmm_plugin_i * p) {
   \a m is not in the linked list yet.\r
 \r
   \note Should only be called from the context of the registrar thread. */\r
-void kmm_init_module(kmm_module_i * m) {\r
+void kmmint_init_module(kmm_module_i * m) {\r
     HMODULE hm;\r
     init_module_t p_init_module;\r
     kmm_plugin_i * pi;\r
@@ -666,6 +718,10 @@ void kmm_init_module(kmm_module_i * m) {
 \r
     /* from this point on, we need to discard the module through\r
        exit_module */\r
+    ResetEvent(evt_exit);\r
+\r
+    kmm_active_modules++;\r
+\r
     release_module = FALSE;\r
     exit_module = TRUE;\r
 \r
@@ -711,7 +767,7 @@ void kmm_init_module(kmm_module_i * m) {
         LPOP(&(m->plugins), &pi);\r
         if(pi) {\r
             pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;\r
-            kmm_init_plugin(pi);\r
+            kmmint_init_plugin(pi);\r
 \r
             /* release the hold obtained in kmm_provide_plugin() */\r
             kmm_release_plugin(kmm_handle_from_plugin(pi));\r
@@ -719,9 +775,14 @@ void kmm_init_module(kmm_module_i * m) {
     } while(pi);\r
 \r
     if(!m->plugin_count) {\r
+        /* We don't want to report this case.  This usually means that\r
+           the plugins that were provided by the module were\r
+           disabled. */\r
+#ifdef REPORT_EMPTY_MODULES\r
         _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS);\r
 \r
         m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS;\r
+#endif\r
         record_failure = FALSE;\r
         goto _exit;\r
     }\r
@@ -731,8 +792,6 @@ void kmm_init_module(kmm_module_i * m) {
     exit_module = FALSE;\r
     record_failure = FALSE;\r
 \r
-    ResetEvent(evt_exit);\r
-\r
  _exit:\r
     if(csp_mod) {\r
         if(record_failure) {\r
@@ -764,7 +823,7 @@ void kmm_init_module(kmm_module_i * m) {
     /* if something went wrong after init_module was called on the\r
        module code, we need to call exit_module */\r
     if(exit_module)\r
-        kmm_exit_module(m);\r
+        kmmint_exit_module(m);\r
 \r
     if(release_module)\r
         kmm_release_module(kmm_handle_from_module(m));\r
@@ -822,21 +881,21 @@ void kmm_init_module(kmm_module_i * m) {
 \r
   \note Should only be called from the context of the registrar\r
   thread */\r
-void kmm_exit_module(kmm_module_i * m) {\r
+void kmmint_exit_module(kmm_module_i * m) {\r
     kmm_plugin_i * p;\r
 \r
-    /*  exiting a module happens in two stages.  \r
-    \r
+    /*  Exiting a module happens in two stages.  \r
+\r
         If the module state is running (there are active plugins) then\r
         those plugins must be exited.  This has to be done from the\r
         plugin threads.  The signal for the plugins to exit must be\r
         issued from the registrar.  Therefore, we post messages to the\r
         registrar for each plugin we want to remove and exit\r
-        kmm_exit_module().\r
+        kmmint_exit_module().\r
 \r
         When the last plugin is exited, the plugin management code\r
         automatically signalls the registrar to remove the module.\r
-        kmm_exit_module() gets called again.  This is the second\r
+        kmmint_exit_module() gets called again.  This is the second\r
         stage, where we call exit_module() for the module and start\r
         unloading everything.\r
     */\r
@@ -847,7 +906,7 @@ void kmm_exit_module(kmm_module_i * m) {
     LPOP(&(m->plugins), &p);\r
     while(p) {\r
         p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST;\r
-        kmm_exit_plugin(p);\r
+        kmmint_exit_plugin(p);\r
 \r
         /* release hold from kmm_provide_plugin() */\r
         kmm_release_plugin(kmm_handle_from_plugin(p));\r
@@ -883,8 +942,7 @@ void kmm_exit_module(kmm_module_i * m) {
         }\r
     }\r
 \r
-    if(m->flags & KMM_MODULE_FLAG_INITP)\r
-    {\r
+    if(m->flags & KMM_MODULE_FLAG_INITP) {\r
         exit_module_t p_exit_module;\r
 \r
         if(m->state > 0)\r
@@ -895,16 +953,16 @@ void kmm_exit_module(kmm_module_i * m) {
                                            EXP_EXIT_MODULE);\r
         if(p_exit_module) {\r
             LeaveCriticalSection(&cs_kmm);\r
-            p_exit_module(kmm_handle_from_module(m));\r
+            (*p_exit_module)(kmm_handle_from_module(m));\r
             EnterCriticalSection(&cs_kmm);\r
         }\r
     }\r
 \r
-    LeaveCriticalSection(&cs_kmm);\r
-\r
     if(m->state > 0)\r
         m->state = KMM_MODULE_STATE_EXITED;\r
 \r
+    LeaveCriticalSection(&cs_kmm);\r
+\r
     if(m->h_module) {\r
         FreeLibrary(m->h_module);\r
     }\r
@@ -917,6 +975,19 @@ void kmm_exit_module(kmm_module_i * m) {
     m->h_resource = NULL;\r
     m->flags = 0;\r
 \r
-    /* release the hold obtained in kmm_init_module() */\r
+    /* release the hold obtained in kmmint_init_module() */\r
     kmm_release_module(kmm_handle_from_module(m));\r
+\r
+    /* Last but not least, now see if there are any modules left that\r
+       are running. If not, we can safely signal an exit. */\r
+\r
+#ifdef DEBUG\r
+    assert(kmm_active_modules > 0);\r
+#endif\r
+\r
+    kmm_active_modules--;\r
+\r
+    if (kmm_active_modules == 0) {\r
+        SetEvent(evt_exit);\r
+    }\r
 }\r
index c4e47238767c460c98c22820a44392cfd451a890..e0ce6b270f8d4d281594c7343e676aac3b9bde3c 100644 (file)
@@ -131,19 +131,23 @@ typedef struct kmm_plugin_i_t {
 #define kmm_plugin_from_handle(ph) ((kmm_plugin_i *) ph)\r
 \r
 /* the plugin has already been marked for unload */\r
-#define KMM_PLUGIN_FLAG_UNLOAD      1\r
-\r
-/* the plugin is disabled by the user\r
-    (option specified in configuration) */\r
-#define KMM_PLUGIN_FLAG_DISABLED    1024\r
+#define KMM_PLUGIN_FLAG_UNLOAD      0x0001\r
 \r
 /* the plugin is in the kmm_listed_plugins list */\r
-#define KMM_PLUGIN_FLAG_IN_LIST     2\r
+#define KMM_PLUGIN_FLAG_IN_LIST     0x0002\r
 \r
 /* the plugin is in the module's plugin list */\r
-#define KMM_PLUGIN_FLAG_IN_MODLIST  4\r
+#define KMM_PLUGIN_FLAG_IN_MODLIST  0x0004\r
+\r
+#define KMM_PLUGIN_FLAG_IN_QUEUE    0x0010\r
+\r
+/* the plugin is disabled by the user\r
+    (option specified in configuration) */\r
+/* (this is defined in kmm.h)\r
+\r
+ #define KMM_PLUGIN_FLAG_DISABLED    0x0400\r
 \r
-#define KMM_PLUGIN_FLAG_IN_QUEUE    0x10\r
+*/\r
 \r
 enum kmm_registrar_uparam_t {\r
     KMM_REG_INIT_MODULE,\r
@@ -153,6 +157,7 @@ enum kmm_registrar_uparam_t {
 };\r
 \r
 extern kmm_module_i * kmm_all_modules;\r
+extern khm_size kmm_active_modules;\r
 extern kmm_plugin_i * kmm_listed_plugins;\r
 extern HANDLE ht_registrar;\r
 extern DWORD tid_registrar;\r
@@ -174,19 +179,19 @@ extern kconf_schema schema_kmmconfig[];
 /* Registrar */\r
 \r
 khm_boolean KHMAPI \r
-kmm_reg_cb(khm_int32 msg_type, \r
-           khm_int32 msg_sub_type, \r
-           khm_ui_4 uparam,\r
-           void *vparam);\r
+kmmint_reg_cb(khm_int32 msg_type, \r
+              khm_int32 msg_sub_type, \r
+              khm_ui_4 uparam,\r
+              void *vparam);\r
 \r
-DWORD WINAPI kmm_registrar(LPVOID lpParameter);\r
+DWORD WINAPI kmmint_registrar(LPVOID lpParameter);\r
 \r
-DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter);\r
+DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter);\r
 \r
-void kmm_init_plugin(kmm_plugin_i * p);\r
-void kmm_exit_plugin(kmm_plugin_i * p);\r
-void kmm_init_module(kmm_module_i * m);\r
-void kmm_exit_module(kmm_module_i * m);\r
+void kmmint_init_plugin(kmm_plugin_i * p);\r
+void kmmint_exit_plugin(kmm_plugin_i * p);\r
+void kmmint_init_module(kmm_module_i * m);\r
+void kmmint_exit_module(kmm_module_i * m);\r
 \r
 /* Modules */\r
 kmm_module_i * \r
index 6489313f80b96f419eadd97b8c79256115f8325f..aa94a59a1a4127864a53fa21a5e164df85e0f421 100644 (file)
@@ -72,7 +72,7 @@ KHMEXP void KHMAPI kmm_init(void)
     ht_registrar = CreateThread(\r
         NULL,\r
         0,\r
-        kmm_registrar,\r
+        kmmint_registrar,\r
         NULL,\r
         0,\r
         &dummy);\r
index 17bc6b80e9c82df6702436310766ca7c78085527..a33c523ac79c580530ed1a97de666061b6465595 100644 (file)
@@ -212,3 +212,48 @@ SymbolicName=MSG_RMI_API_MISMATCH
 Language=English\r
 The module was compile for API version %1!d!.  However the current API version is %2!d!.\r
 .\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_START\r
+Language=English\r
+Starting plugin [%1!s!]\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INVALID_CODE_PTR\r
+Language=English\r
+The plugin is no longer valid.  This maybe because the module containing the plugin was unloaded.\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INIT_RV\r
+Language=English\r
+Initialization of the plugin returned code %1!d!.\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INIT_FAIL\r
+Language=English\r
+Initialization of the %1!s! plugin failed.  The plugin will be unloaded and any functionality provided will not be available.\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INIT_FAIL_S\r
+Language=English\r
+Plugin %1!s! failed to initialize\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INIT_FAIL_G\r
+Language=English\r
+Details for plugin:\r
+Description: %2!s!\r
+Module: %3!s!\r
+Support: %4!s!\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_PB_INIT_DONE\r
+Language=English\r
+Plugin running\r
+.\r
index 03519bafd6bad6bf6b6a2ca36237e0fadee6aaa6..ed7d548f10841b55fe0138284c42fb9d15dbf64e 100644 (file)
@@ -216,6 +216,8 @@ KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd) {
     kmq_msg_subscription * s;\r
 \r
     s = PMALLOC(sizeof(kmq_msg_subscription));\r
+    ZeroMemory(s, sizeof(*s));\r
+    s->magic = KMQ_MSG_SUB_MAGIC;\r
     LINIT(s);\r
     s->queue = NULL;\r
     s->rcpt_type = KMQ_RCPTTYPE_HWND;\r
@@ -232,6 +234,8 @@ KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb) {
     kmq_msg_subscription * s;\r
 \r
     s = PMALLOC(sizeof(kmq_msg_subscription));\r
+    ZeroMemory(s, sizeof(*s));\r
+    s->magic = KMQ_MSG_SUB_MAGIC;\r
     LINIT(s);\r
     s->queue = kmqint_get_thread_queue();\r
     s->rcpt_type = KMQ_RCPTTYPE_CB;\r
@@ -241,6 +245,28 @@ KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb) {
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
+KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,\r
+                                                     khm_handle * result)\r
+{\r
+    kmq_msg_subscription * s;\r
+\r
+    s = PMALLOC(sizeof(kmq_msg_subscription));\r
+    ZeroMemory(s, sizeof(*s));\r
+    s->magic = KMQ_MSG_SUB_MAGIC;\r
+    LINIT(s);\r
+    s->queue = NULL;\r
+    s->rcpt_type = KMQ_RCPTTYPE_HWND;\r
+    s->recipient.hwnd = hw;\r
+\r
+    EnterCriticalSection(&cs_kmq_global);\r
+    LPUSH(&kmq_adhoc_subs, s);\r
+    LeaveCriticalSection(&cs_kmq_global);\r
+\r
+    *result = (khm_handle) s;\r
+\r
+    return KHM_ERROR_SUCCESS;\r
+}\r
+\r
 /*! \internal\r
     \note Obtains ::cs_kmq_global\r
 */\r
@@ -250,6 +276,8 @@ KHMEXP khm_int32 KHMAPI kmq_create_subscription(kmq_callback_t cb,
     kmq_msg_subscription * s;\r
 \r
     s = PMALLOC(sizeof(kmq_msg_subscription));\r
+    ZeroMemory(s, sizeof(*s));\r
+    s->magic = KMQ_MSG_SUB_MAGIC;\r
     LINIT(s);\r
     s->queue = kmqint_get_thread_queue();\r
     s->rcpt_type = KMQ_RCPTTYPE_CB;\r
@@ -270,6 +298,8 @@ KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub)
 \r
     s = (kmq_msg_subscription *) sub;\r
 \r
+    assert(s->magic == KMQ_MSG_SUB_MAGIC);\r
+\r
     s->type = 0;\r
 \r
     EnterCriticalSection(&cs_kmq_global);\r
index f157e6ab222df52ad1036225f8fd955d0bb31d15..77b8dd0e14b101a9cb392818771712b348c73504 100644 (file)
@@ -77,10 +77,10 @@ void kmqint_exit(void) {
 void kmqint_attach_this_thread(void) {\r
     kmq_queue * q;\r
 \r
+    EnterCriticalSection(&cs_kmq_global);\r
+\r
     q = (kmq_queue *) TlsGetValue(kmq_tls_queue);\r
     if(!q) {\r
-        EnterCriticalSection(&cs_kmq_global);\r
-\r
         q = PMALLOC(sizeof(kmq_queue));\r
 \r
         InitializeCriticalSection(&q->cs);\r
@@ -90,13 +90,14 @@ void kmqint_attach_this_thread(void) {
         q->wait_o = CreateEvent(NULL, FALSE, FALSE, NULL);\r
         q->load = 0;\r
         q->last_post = 0;\r
+        q->flags = 0;\r
 \r
         LPUSH(&queues, q);\r
 \r
         TlsSetValue(kmq_tls_queue, (LPVOID) q);\r
-\r
-        LeaveCriticalSection(&cs_kmq_global);\r
     }\r
+\r
+    LeaveCriticalSection(&cs_kmq_global);\r
 }\r
 \r
 /*! \internal\r
@@ -108,18 +109,11 @@ void kmqint_detach_this_thread(void) {
 \r
     q = (kmq_queue *) TlsGetValue(kmq_tls_queue);\r
     if(q) {\r
-        EnterCriticalSection(&cs_kmq_global);\r
-\r
-        LDELETE(&queues, q);\r
-        \r
-        DeleteCriticalSection(&q->cs);\r
-        CloseHandle(q->wait_o);\r
+        EnterCriticalSection(&q->cs);\r
+        q->flags |= KMQ_QUEUE_FLAG_DELETED;\r
+        LeaveCriticalSection(&q->cs);\r
 \r
         /* TODO: free up the queued messages */\r
-\r
-        TlsSetValue(kmq_tls_queue, (LPVOID) 0);\r
-\r
-        LeaveCriticalSection(&cs_kmq_global);\r
     }\r
 }\r
 \r
index 4c8c610cd84ef38cd415e7694f502a0e7e3bd6d9..fef6a30969ccb3faae2ca542fdea45e479441959 100644 (file)
@@ -149,6 +149,8 @@ typedef struct tag_kmq_queue {
     kmq_timer last_post;        /*!< Time the last message was\r
                                   received */\r
 \r
+    khm_int32 flags;            /*!< Flags.  Currently, it's just KMQ_QUEUE_FLAG_DELETED */\r
+\r
     /*Q*/\r
     QDCL(kmq_message_ref);      /*!< Queue of message references  */\r
 \r
@@ -156,6 +158,8 @@ typedef struct tag_kmq_queue {
     LDCL(struct tag_kmq_queue);\r
 } kmq_queue;\r
 \r
+#define KMQ_QUEUE_FLAG_DELETED 0x0008\r
+\r
 /*! \brief Message subscription\r
 \r
     A subscription binds a recipient with a message type.  These are\r
@@ -163,6 +167,8 @@ typedef struct tag_kmq_queue {
     thread will not receive messages in the context of another thread.\r
 */\r
 typedef struct tag_kmq_msg_subscription {\r
+    khm_int32 magic;            /*!< Magic number.  Should always be\r
+                                  ::KMQ_MSG_SUB_MAGIC */\r
     khm_int32 type;             /*!< Type of message */\r
     khm_int32 rcpt_type;        /*!< Type of recipient.  One of\r
                                   ::KMQ_RCPTTYPE_CB or\r
@@ -180,6 +186,8 @@ typedef struct tag_kmq_msg_subscription {
     LDCL(struct tag_kmq_msg_subscription);\r
 } kmq_msg_subscription;\r
 \r
+#define KMQ_MSG_SUB_MAGIC 0x3821b58e\r
+\r
 /*! \brief Callback recipient type\r
 \r
     The recipient is a callback function */\r
@@ -482,6 +490,19 @@ KHMEXP khm_int32 KHMAPI kmq_create_subscription(
     kmq_callback_t cb, \r
     khm_handle * result);\r
 \r
+/*! \brief Create an ad-hoc subscription for a window\r
+\r
+    An ad-hoc subscription describes a window that will be dispatched\r
+    messages individually without broadcasting.\r
+\r
+    \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(),\r
+        kmq_send_sub_msg(), kmq_post_subs_msg(),\r
+        kmq_post_subs_msg_ex(), kmq_send_subs_msg(),\r
+        kmq_delete_subscription()\r
+ */\r
+KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw,\r
+                                                     khm_handle * result);\r
+\r
 /*! \brief Delete an ad-hoc subscription\r
 \r
     Deletes a subscriptoin that was created using\r
index 03d3c3d541ea9d8db040e1d1462647a8303663a5..d3f50021c6b5de1ee89f9a9008e86a8cd5200d07 100644 (file)
-#\r
-# Copyright (c) 2004 Massachusetts Institute of Technology\r
-#\r
-# Permission is hereby granted, free of charge, to any person\r
-# obtaining a copy of this software and associated documentation files\r
-# (the "Software"), to deal in the Software without restriction,\r
-# including without limitation the rights to use, copy, modify, merge,\r
-# publish, distribute, sublicense, and/or sell copies of the Software,\r
-# and to permit persons to whom the Software is furnished to do so,\r
-# subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be\r
-# included in all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-# SOFTWARE.\r
-\r
-\r
-MODULE=nidmgrdll\r
-!include <../config/Makefile.w32>\r
-\r
-DLLFILE=$(BINDIR)\nidmgr32.dll\r
-\r
-LIBFILE=$(LIBDIR)\nidmgr32.lib\r
-\r
-UTILDIR=$(OBJDIR)\util\r
-\r
-KHERRDIR=$(OBJDIR)\kherr\r
-\r
-KCONFIGDIR=$(OBJDIR)\kconfig\r
-\r
-KMQDIR=$(OBJDIR)\kmq\r
-\r
-KCDBDIR=$(OBJDIR)\kcreddb\r
-\r
-KMMDIR=$(OBJDIR)\kmm\r
-\r
-UIDIR=$(OBJDIR)\uilib\r
-\r
-OBJFILES= \\r
-       $(OBJ)\dllmain.obj              \\r
-       $(UTILDIR)\hashtable.obj        \\r
-       $(UTILDIR)\sync.obj             \\r
-       $(UTILDIR)\mstring.obj          \\r
-       $(UTILDIR)\perfstat.obj         \\r
-       $(KHERRDIR)\kherrmain.obj       \\r
-       $(KHERRDIR)\kherr.obj           \\r
-       $(KCONFIGDIR)\kconfigmain.obj   \\r
-       $(KCONFIGDIR)\api.obj           \\r
-       $(KMQDIR)\kmqmain.obj           \\r
-       $(KMQDIR)\init.obj              \\r
-       $(KMQDIR)\msgtype.obj           \\r
-       $(KMQDIR)\consumer.obj          \\r
-       $(KMQDIR)\publisher.obj         \\r
-       $(KMQDIR)\kmqconfig.obj         \\r
-       $(KCDBDIR)\buf.obj              \\r
-       $(KCDBDIR)\attrib.obj           \\r
-       $(KCDBDIR)\credential.obj       \\r
-       $(KCDBDIR)\credset.obj          \\r
-       $(KCDBDIR)\credtype.obj         \\r
-       $(KCDBDIR)\identity.obj         \\r
-       $(KCDBDIR)\init.obj             \\r
-       $(KCDBDIR)\kcreddbmain.obj      \\r
-       $(KCDBDIR)\type.obj             \\r
-       $(KCDBDIR)\kcdbconfig.obj       \\r
-       $(KMMDIR)\kmmmain.obj           \\r
-       $(KMMDIR)\kmm.obj               \\r
-       $(KMMDIR)\kmm_plugin.obj        \\r
-       $(KMMDIR)\kmm_module.obj        \\r
-       $(KMMDIR)\kmm_reg.obj           \\r
-       $(KMMDIR)\kmm_registrar.obj     \\r
-       $(KMMDIR)\kmmconfig.obj         \\r
-       $(UIDIR)\rescache.obj           \\r
-       $(UIDIR)\action.obj             \\r
-       $(UIDIR)\creddlg.obj            \\r
-       $(UIDIR)\alert.obj              \\r
-       $(UIDIR)\propsheet.obj          \\r
-       $(UIDIR)\propwnd.obj            \\r
-       $(UIDIR)\uilibmain.obj          \\r
-       $(UIDIR)\actiondef.obj          \\r
-       $(UIDIR)\acceldef.obj           \\r
-       $(UIDIR)\configui.obj           \\r
-       $(UIDIR)\trackerwnd.obj         \\r
-       $(UIDIR)\version.obj\r
-\r
-RESFILES= \\r
-       $(OBJ)\nidmgrdll.res            \\r
-       $(KCDBDIR)\kcredres.res         \\r
-       $(KMMDIR)\kmm_msgs.res          \\r
-\r
-SDKLIBFILES= \\r
-       advapi32.lib                    \\r
-       strsafe.lib                     \\r
-       comctl32.lib                    \\r
-       shlwapi.lib                     \\r
-       version.lib\r
-\r
-$(DLLFILE): $(OBJFILES) $(RESFILES)\r
-       $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)\r
-\r
-all: mkdirs $(DLLFILE)\r
-\r
-clean::\r
-       $(RM) $(DLLFILE)\r
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=nidmgrdll
+!include <../config/Makefile.w32>
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+DLLFILE=$(BINDIR)\nidmgr64.dll
+LIBFILE=$(LIBDIR)\nidmgr64.lib
+!else
+DLLFILE=$(BINDIR)\nidmgr32.dll
+LIBFILE=$(LIBDIR)\nidmgr32.lib
+!endif
+
+UTILDIR=$(OBJDIR)\util
+
+KHERRDIR=$(OBJDIR)\kherr
+
+KCONFIGDIR=$(OBJDIR)\kconfig
+
+KMQDIR=$(OBJDIR)\kmq
+
+KCDBDIR=$(OBJDIR)\kcreddb
+
+KMMDIR=$(OBJDIR)\kmm
+
+UIDIR=$(OBJDIR)\uilib
+
+OBJFILES= \
+       $(OBJ)\dllmain.obj              \
+       $(UTILDIR)\hashtable.obj        \
+       $(UTILDIR)\sync.obj             \
+       $(UTILDIR)\mstring.obj          \
+       $(UTILDIR)\perfstat.obj         \
+       $(KHERRDIR)\kherrmain.obj       \
+       $(KHERRDIR)\kherr.obj           \
+       $(KCONFIGDIR)\kconfigmain.obj   \
+       $(KCONFIGDIR)\api.obj           \
+       $(KMQDIR)\kmqmain.obj           \
+       $(KMQDIR)\init.obj              \
+       $(KMQDIR)\msgtype.obj           \
+       $(KMQDIR)\consumer.obj          \
+       $(KMQDIR)\publisher.obj         \
+       $(KMQDIR)\kmqconfig.obj         \
+       $(KCDBDIR)\buf.obj              \
+       $(KCDBDIR)\attrib.obj           \
+       $(KCDBDIR)\credential.obj       \
+       $(KCDBDIR)\credset.obj          \
+       $(KCDBDIR)\credtype.obj         \
+       $(KCDBDIR)\identity.obj         \
+       $(KCDBDIR)\init.obj             \
+       $(KCDBDIR)\kcreddbmain.obj      \
+       $(KCDBDIR)\type.obj             \
+       $(KCDBDIR)\kcdbconfig.obj       \
+       $(KMMDIR)\kmmmain.obj           \
+       $(KMMDIR)\kmm.obj               \
+       $(KMMDIR)\kmm_plugin.obj        \
+       $(KMMDIR)\kmm_module.obj        \
+       $(KMMDIR)\kmm_reg.obj           \
+       $(KMMDIR)\kmm_registrar.obj     \
+       $(KMMDIR)\kmmconfig.obj         \
+       $(UIDIR)\rescache.obj           \
+       $(UIDIR)\action.obj             \
+       $(UIDIR)\creddlg.obj            \
+       $(UIDIR)\alert.obj              \
+       $(UIDIR)\propsheet.obj          \
+       $(UIDIR)\propwnd.obj            \
+       $(UIDIR)\uilibmain.obj          \
+       $(UIDIR)\actiondef.obj          \
+       $(UIDIR)\acceldef.obj           \
+       $(UIDIR)\configui.obj           \
+       $(UIDIR)\trackerwnd.obj         \
+       $(UIDIR)\version.obj
+
+RESFILES= \
+       $(OBJ)\nidmgrdll.res            \
+       $(KCDBDIR)\kcredres.res         \
+       $(KMMDIR)\kmm_msgs.res          \
+
+SDKLIBFILES= \
+       advapi32.lib                    \
+       strsafe.lib                     \
+       comctl32.lib                    \
+       shlwapi.lib                     \
+       version.lib
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+!else
+SCLIB=
+!endif
+
+$(DLLFILE): $(OBJFILES) $(RESFILES)
+       $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB)
+
+all: mkdirs $(DLLFILE)
+
+clean::
+       $(RM) $(DLLFILE)
index b906b6ae98065aeaba298fa0b60015e12b806b90..016af86e980131c294a977ed838891e406570b24 100644 (file)
@@ -360,15 +360,33 @@ FUNC_INFO toolhelp_fi[] = {
 \r
 khm_int32 init_imports(void) {\r
     OSVERSIONINFO osvi;\r
+    int imp_rv = 1;\r
 \r
-    LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);\r
-    LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);\r
-    LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);\r
-    LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);\r
-    LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);\r
-    LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);\r
-    LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);\r
-    LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);\r
+#define CKRV if(!imp_rv) goto _err_ret\r
+\r
+    imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);\r
+    CKRV;\r
+\r
+    imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);\r
+    CKRV;\r
 \r
     memset(&osvi, 0, sizeof(OSVERSIONINFO));\r
     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
@@ -382,19 +400,26 @@ khm_int32 init_imports(void) {
     if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)\r
     {\r
         // Windows 9x\r
-        LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);\r
+        imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);\r
+        CKRV;\r
+\r
         hPsapi = 0;\r
     }             \r
     else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)\r
     {\r
         // Windows NT\r
-        LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);\r
+        imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);\r
+        CKRV;\r
+\r
         hToolHelp32 = 0;\r
     }\r
 \r
     AfsAvailable = TRUE; //afscompat_init();\r
 \r
     return KHM_ERROR_SUCCESS;\r
+\r
+ _err_ret:\r
+    return KHM_ERROR_NOT_FOUND;\r
 }\r
 \r
 khm_int32 exit_imports(void) {\r
index 2385e617937751e63abad7009058ecef90c040c9..b1ad963f080ab0448f61f9bd75414ca45c11fb31 100644 (file)
-#\r
-# Copyright (c) 2004 Massachusetts Institute of Technology\r
-#\r
-# Permission is hereby granted, free of charge, to any person\r
-# obtaining a copy of this software and associated documentation files\r
-# (the "Software"), to deal in the Software without restriction,\r
-# including without limitation the rights to use, copy, modify, merge,\r
-# publish, distribute, sublicense, and/or sell copies of the Software,\r
-# and to permit persons to whom the Software is furnished to do so,\r
-# subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be\r
-# included in all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-# SOFTWARE.\r
-\r
-\r
-MODULE=plugins\krb4\r
-!include <../../config/Makefile.w32>\r
-\r
-DLLFILE=$(BINDIR)\krb4cred.dll\r
-\r
-LIBFILE=$(LIBDIR)\krb4cred.lib\r
-\r
-OBJFILES=                              \\r
-       $(LIBDIR)\dynimport.obj         \\r
-       $(LIBDIR)\krb5common.obj        \\r
-       $(OBJ)\krb4main.obj             \\r
-       $(OBJ)\krb4plugin.obj           \\r
-       $(OBJ)\krb4funcs.obj            \\r
-       $(OBJ)\errorfuncs.obj           \\r
-       $(OBJ)\krb4config.obj           \\r
-       $(OBJ)\krb4configdlg.obj        \\r
-       $(OBJ)\krb4newcreds.obj\r
-\r
-LIBFILES=                              \\r
-       $(LIBDIR)\nidmgr32.lib          \\r
-       $(KFWLIBDIR)\loadfuncs.lib\r
-\r
-SDKLIBFILES=\r
-\r
-VERRESFILE=$(OBJ)\version.res\r
-\r
-$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg\r
-       $(CCSV) $** $@\r
-\r
-$(DLLFILE): $(OBJFILES) $(VERRESFILE)\r
-       $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)\r
-\r
-all: mkdirs $(DLLFILE) lang\r
-\r
-lang::\r
-\r
-# Repeat this block as necessary redefining LANG for additional\r
-# languages.\r
-\r
-# Begin language block\r
-LANG=en_us\r
-\r
-LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll\r
-\r
-lang:: $(LANGDLL)\r
-\r
-$(LANGDLL): $(OBJ)\langres_$(LANG).res\r
-       $(DLLRESLINK)\r
-\r
-$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc\r
-       $(RC2RES)\r
-# End language block\r
-\r
-clean::\r
-!if defined(INCFILES)\r
-       $(RM) $(INCFILES)\r
-!endif\r
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb4
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb4cred.dll
+
+LIBFILE=$(LIBDIR)\krb4cred.lib
+
+OBJFILES=                              \
+       $(LIBDIR)\dynimport.obj         \
+       $(LIBDIR)\krb5common.obj        \
+       $(OBJ)\krb4main.obj             \
+       $(OBJ)\krb4plugin.obj           \
+       $(OBJ)\krb4funcs.obj            \
+       $(OBJ)\errorfuncs.obj           \
+       $(OBJ)\krb4config.obj           \
+       $(OBJ)\krb4configdlg.obj        \
+       $(OBJ)\krb4newcreds.obj
+
+
+
+SDKLIBFILES=
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+LIBFILES=                              \
+       $(LIBDIR)\nidmgr64.lib          \
+       $(KFWLIBDIR)\loadfuncs.lib
+!else
+SCLIB=
+LIBFILES=                              \
+       $(LIBDIR)\nidmgr32.lib          \
+       $(KFWLIBDIR)\loadfuncs.lib
+!endif
+
+VERRESFILE=$(OBJ)\version.res
+
+MSGRESFILE=$(OBJ)\krb4_msgs.res
+
+$(MSGRESFILE): $(OBJ)\krb4_msgs.rc
+
+$(OBJ)\krb4_msgs.rc: lang\krb4_msgs.mc
+       $(MC2RC)
+
+$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+       $(CCSV) $** $@
+
+$(DLLFILE): $(OBJFILES) $(VERRESFILE) $(MSGRESFILE)
+       $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB)
+
+all: mkdirs $(MSGRESFILE) $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res
+       $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+       $(RC2RES)
+
+$(OBJ)\langres_ver_$(LANG).res: version.rc
+       $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $** 
+# End language block
+
+clean::
+!if defined(INCFILES)
+       $(RM) $(INCFILES)
+!endif
index 7798e5c9ede962701ae36c6573795da33479496e..8928f71fdea924a4019bee9603a258aca0d3b857 100644 (file)
@@ -182,15 +182,16 @@ khm_krb4_list_tickets(void)
 \r
         kcdb_credset_add_cred(krb4_credset, cred, -1);\r
 \r
+       kcdb_cred_release(cred);\r
     } // while\r
 \r
-cleanup:\r
+ cleanup:\r
     if (ptf_close == NULL)\r
         return(KSUCCESS);\r
 \r
     if (open)\r
         (*ptf_close)(); //close ticket file \r
-    \r
+\r
     if (k_errno == EOF)\r
         k_errno = 0;\r
 \r
@@ -601,6 +602,76 @@ khm_krb4_changepwd(char * principal,
     return k_errno;\r
 }\r
 \r
+struct tgt_filter_data {\r
+    khm_handle identity;\r
+    wchar_t realm[KCDB_IDENT_MAXCCH_NAME];\r
+};\r
+\r
+khm_int32 KHMAPI\r
+krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) {\r
+    struct tgt_filter_data * pdata;\r
+    wchar_t credname[KCDB_MAXCCH_NAME];\r
+    wchar_t * t;\r
+    khm_size cb;\r
+    khm_int32 ctype;\r
+\r
+    pdata = (struct tgt_filter_data *) rock;\r
+    cb = sizeof(credname);\r
+\r
+    if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) ||\r
+        ctype != credtype_id_krb4)\r
+        return 0;\r
+\r
+    if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb)))\r
+        return 0;\r
+\r
+    if (wcsncmp(credname, L"krbtgt.", 7))\r
+        return 0;\r
+\r
+    t = wcsrchr(credname, L'@');\r
+    if (t == NULL)\r
+        return 0;\r
+\r
+    if (wcscmp(t+1, pdata->realm))\r
+        return 0;\r
+\r
+    return 1;\r
+}\r
+\r
+khm_handle\r
+khm_krb4_find_tgt(khm_handle credset, khm_handle identity) {\r
+    khm_handle result = NULL;\r
+    wchar_t idname[KCDB_IDENT_MAXCCH_NAME];\r
+    wchar_t * t;\r
+    khm_size cb;\r
+    struct tgt_filter_data filter_data;\r
+\r
+    cb = sizeof(idname);\r
+\r
+    if (KHM_FAILED(kcdb_identity_get_name(identity,\r
+                                          idname,\r
+                                          &cb)))\r
+        return NULL;\r
+    \r
+    t = wcsrchr(idname, L'@');\r
+    if (t == NULL)\r
+        return NULL;\r
+\r
+    StringCbCopy(filter_data.realm, sizeof(filter_data.realm),\r
+                 t + 1);\r
+    filter_data.identity = identity;\r
+\r
+    if (KHM_FAILED(kcdb_credset_find_filtered(credset,\r
+                                              -1,\r
+                                              krb4_tgt_filter,\r
+                                              &filter_data,\r
+                                              &result,\r
+                                              NULL)))\r
+        return NULL;\r
+    else\r
+        return result;\r
+}\r
+\r
 long\r
 khm_convert524(khm_handle identity)\r
 {\r
@@ -677,6 +748,7 @@ khm_convert524(khm_handle identity)
          != KSUCCESS)) {\r
         goto cleanup;\r
     }\r
+\r
     /* stash ticket, session key, etc. for future use */\r
     if ((icode = pkrb_save_credentials(v4creds->service,\r
                                        v4creds->instance,\r
index 742036878fc7f27f2eaa843ceb72d5fb76b047d3..8abb7ac33870a7ad6e7eb14180a7ecbeeccf7900 100644 (file)
@@ -64,6 +64,10 @@ khm_krb4_list_tickets(void);
 \r
 int khm_krb4_kdestroy(void);\r
 \r
+khm_handle\r
+khm_krb4_find_tgt(khm_handle credset, \r
+                  khm_handle identity);\r
+\r
 LONG\r
 write_registry_setting(\r
     char* setting,\r
index b83cd5eb42fae01f3ae3583968c4796e80c690ea..57e33a8d8b98ea4633da7b08eec4208970188ddb 100644 (file)
@@ -74,7 +74,8 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
     ZeroMemory(&pi, sizeof(pi));\r
     pi.name = KRB4_PLUGIN_NAME;\r
     pi.type = KHM_PITYPE_CRED;\r
-    pi.icon = NULL; /*TODO: Assign icon */\r
+    pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),\r
+                        IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);\r
     pi.flags = 0;\r
     pi.msg_proc = krb4_cb;\r
     pi.dependencies = KRB4_PLUGIN_DEPS;\r
@@ -101,7 +102,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
     rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);\r
     if(KHM_FAILED(rv)) goto _exit;\r
 \r
-_exit:\r
+ _exit:\r
     return rv;\r
 }\r
 \r
@@ -114,17 +115,19 @@ KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
         khc_close_space(csp_params);\r
         csp_params = NULL;\r
     }\r
+\r
     if(csp_krbcred) {\r
         khc_close_space(csp_krbcred);\r
         csp_krbcred = NULL;\r
     }\r
+\r
     if(csp_plugins) {\r
         khc_unload_schema(csp_plugins, schema_krbconfig);\r
         khc_close_space(csp_plugins);\r
         csp_plugins = NULL;\r
     }\r
 \r
-    return KHM_ERROR_SUCCESS; /* the return code is ignored */\r
+    return KHM_ERROR_SUCCESS;  /* the return code is ignored */\r
 }\r
 \r
 BOOL WINAPI DllMain(\r
@@ -138,11 +141,14 @@ BOOL WINAPI DllMain(
             hInstance = hinstDLL;\r
             init_krb();\r
             break;\r
+\r
         case DLL_PROCESS_DETACH:\r
             exit_krb();\r
             break;\r
+\r
         case DLL_THREAD_ATTACH:\r
             break;\r
+\r
         case DLL_THREAD_DETACH:\r
             break;\r
     }\r
index 28ae71a1ff93370654e65bfe38668786a05e5598..3a1a72bfacdd99b414c72a7df81dc212fa3beecb 100644 (file)
@@ -55,6 +55,7 @@ typedef struct tag_k4_dlg_data {
 } k4_dlg_data;\r
 \r
 void k4_update_display(k4_dlg_data * d) {\r
+\r
     CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN,\r
                    (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED);\r
 \r
@@ -68,8 +69,11 @@ void k4_update_display(k4_dlg_data * d) {
         EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE);\r
     }\r
 \r
-    CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD,\r
-                     method_to_id[d->method]);\r
+#ifdef DEBUG\r
+    assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id));\r
+#endif\r
+\r
+    CheckDlgButton(d->hwnd, method_to_id[d->method], BST_CHECKED);\r
 \r
     khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);\r
 }\r
@@ -103,6 +107,9 @@ void k4_update_data(k4_dlg_data * d) {
 \r
 khm_boolean k4_should_identity_get_k4(khm_handle ident) {\r
     khm_int32 idflags = 0;\r
+    khm_handle csp_ident = NULL;\r
+    khm_handle csp_k4 = NULL;\r
+    khm_boolean get_k4 = TRUE;\r
 \r
     if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags)))\r
         return FALSE;\r
@@ -122,7 +129,20 @@ khm_boolean k4_should_identity_get_k4(khm_handle ident) {
         }\r
     }\r
 \r
-    return TRUE;\r
+    if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) {\r
+        if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0,\r
+                                         &csp_k4))) {\r
+            khm_int32 t = 0;\r
+            if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t)) &&\r
+                !t)\r
+                get_k4 = FALSE;\r
+\r
+            khc_close_space(csp_k4);\r
+        }\r
+        khc_close_space(csp_ident);\r
+    }\r
+\r
+    return get_k4;\r
 }\r
 \r
 void k4_read_identity_data(k4_dlg_data * d) {\r
@@ -433,9 +453,6 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
             if (!nc->ctx.identity)\r
                 break;\r
 \r
-            if (!k4_should_identity_get_k4(nc->ctx.identity))\r
-                break;\r
-\r
             nct = PMALLOC(sizeof(*nct));\r
 #ifdef DEBUG\r
             assert(nct);\r
@@ -469,6 +486,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
             khm_handle ident = NULL;\r
             k4_dlg_data * d = NULL;\r
             long code = 0;\r
+            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];\r
+            khm_size cb;\r
 \r
             nc = (khui_new_creds *) vparam;\r
             if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))\r
@@ -484,17 +503,33 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                     if (!d ||\r
                         nc->n_identities == 0 ||\r
                         nc->identities[0] == NULL ||\r
-                        nc->result != KHUI_NC_RESULT_GET_CREDS)\r
+                        nc->result != KHUI_NC_RESULT_PROCESS) {\r
+                        khui_cw_set_response(nc, credtype_id_krb4,\r
+                                             KHUI_NC_RESPONSE_SUCCESS |\r
+                                             KHUI_NC_RESPONSE_EXIT);\r
                         break;\r
+                    }\r
 \r
                     if (!d->k4_enabled) {\r
                         k4_write_identity_data(d);\r
+                        khui_cw_set_response(nc, credtype_id_krb4,\r
+                                             KHUI_NC_RESPONSE_SUCCESS |\r
+                                             KHUI_NC_RESPONSE_EXIT);\r
                         break;\r
                     }\r
 \r
                     method = d->method;\r
                     ident = nc->identities[0];\r
 \r
+                    cb = sizeof(idname);\r
+                    kcdb_identity_get_name(ident, idname, &cb);\r
+                    _begin_task(0);\r
+                    _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS,\r
+                                _cstr(ident), _int32(method));\r
+                    _resolve();\r
+                    _describe();\r
+                                \r
+\r
                 } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {\r
 \r
                     if ((nc->ctx.scope == KHUI_SCOPE_IDENT &&\r
@@ -511,12 +546,30 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
 \r
                         ident = nc->ctx.identity;\r
 \r
+                        if (!k4_should_identity_get_k4(ident)) {\r
+                            khui_cw_set_response(nc, credtype_id_krb4,\r
+                                                 KHUI_NC_RESPONSE_FAILED |\r
+                                                 KHUI_NC_RESPONSE_EXIT);\r
+                            break;\r
+                        }\r
+\r
                     } else {\r
+                        khui_cw_set_response(nc, credtype_id_krb4,\r
+                                             KHUI_NC_RESPONSE_FAILED |\r
+                                             KHUI_NC_RESPONSE_EXIT);\r
                         break;\r
                     }\r
 \r
                     method = K4_METHOD_K524; /* only k524 is supported\r
                                                 for renewals */\r
+\r
+                    _begin_task(0);\r
+                    cb = sizeof(idname);\r
+                    kcdb_identity_get_name(ident, idname, &cb);\r
+                    _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS,\r
+                                _cstr(ident), _int32(method));\r
+                    _resolve();\r
+                    _describe();\r
                 } else {\r
                     assert(FALSE);\r
                 }\r
@@ -525,8 +578,29 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                      method == K4_METHOD_K524) &&\r
                     khui_cw_type_succeeded(nc, credtype_id_krb5)) {\r
 \r
+                    khm_handle tgt;\r
+                    FILETIME ft_prev;\r
+                    FILETIME ft_new;\r
+                    khm_size cb;\r
+\r
+                    _report_mr0(KHERR_INFO, MSG_K4_TRY_K524);\r
+\r
+                    tgt = khm_krb4_find_tgt(NULL, ident);\r
+                    if (tgt) {\r
+                        cb = sizeof(ft_prev);\r
+                        if (KHM_FAILED(kcdb_cred_get_attr(tgt,\r
+                                                          KCDB_ATTR_EXPIRE,\r
+                                                          NULL,\r
+                                                          &ft_prev,\r
+                                                          &cb)))\r
+                            ZeroMemory(&ft_prev, sizeof(ft_prev));\r
+                        kcdb_cred_release(tgt);\r
+                    }\r
+\r
                     code = khm_convert524(ident);\r
 \r
+                    _reportf(L"khm_convert524 returns code %d", code);\r
+\r
                     if (code == 0) {\r
                         khui_cw_set_response(nc, credtype_id_krb4,\r
                                              KHUI_NC_RESPONSE_SUCCESS |\r
@@ -536,13 +610,92 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                             assert(d != NULL);\r
 \r
                             k4_write_identity_data(d);\r
+\r
+                        } else if (nc->subtype == KMSG_CRED_RENEW_CREDS &&\r
+                                   (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||\r
+                                    nc->ctx.scope == KHUI_SCOPE_CRED)) {\r
+\r
+                            khm_krb4_list_tickets();\r
+\r
+                            tgt = khm_krb4_find_tgt(NULL, ident);\r
+\r
+                            if (tgt) {\r
+                                cb = sizeof(ft_new);\r
+                                ZeroMemory(&ft_new, sizeof(ft_new));\r
+\r
+                                kcdb_cred_get_attr(tgt,\r
+                                                   KCDB_ATTR_EXPIRE,\r
+                                                   NULL,\r
+                                                   &ft_new,\r
+                                                   &cb);\r
+\r
+                                kcdb_cred_release(tgt);\r
+                            }\r
+\r
+                            if (!tgt ||\r
+                                CompareFileTime(&ft_new,\r
+                                                &ft_prev) <= 0) {\r
+                                /* The new TGT wasn't much of an\r
+                                   improvement over what we already\r
+                                   had.  We should go out and try to\r
+                                   renew the identity now. */\r
+\r
+                                khui_action_context ctx;\r
+\r
+                                _reportf(L"Renewal of Krb4 creds failed to get a longer TGT.  Triggering identity renewal");\r
+\r
+                                khui_context_create(&ctx,\r
+                                                    KHUI_SCOPE_IDENT,\r
+                                                    nc->ctx.identity,\r
+                                                    KCDB_CREDTYPE_INVALID,\r
+                                                    NULL);\r
+                                khui_action_trigger(KHUI_ACTION_RENEW_CRED,\r
+                                                    &ctx);\r
+\r
+                                khui_context_release(&ctx);\r
+                            }\r
                         }\r
+\r
+                        _end_task();\r
                         break;\r
+\r
                     } else if (method == K4_METHOD_K524) {\r
                         khui_cw_set_response(nc, credtype_id_krb4,\r
                                              KHUI_NC_RESPONSE_FAILED |\r
                                              KHUI_NC_RESPONSE_EXIT);\r
+\r
+                       if (nc->subtype == KMSG_CRED_RENEW_CREDS &&\r
+                           (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||\r
+                            nc->ctx.scope == KHUI_SCOPE_CRED)) {\r
+                           /* We were trying to get a new Krb4 TGT\r
+                              for this identity.  Sometimes this\r
+                              fails because of restrictions placed on\r
+                              K524d regarding the lifetime of the\r
+                              issued K4 TGT.  In this case, we\r
+                              trigger a renewal of the identity in\r
+                              the hope that the new K5 TGT will allow\r
+                              us to successfully get a new K4 TGT\r
+                              next time over using the new K5 TGT. */\r
+\r
+                           khui_action_context ctx;\r
+\r
+                            _reportf(L"Renewal of Krb4 creds failed using k524.  Triggerring identity renewal.");\r
+\r
+                           khui_context_create(&ctx,\r
+                                               KHUI_SCOPE_IDENT,\r
+                                               nc->ctx.identity,\r
+                                               KCDB_CREDTYPE_INVALID,\r
+                                               NULL);\r
+\r
+                           khui_action_trigger(KHUI_ACTION_RENEW_CRED,\r
+                                               &ctx);\r
+\r
+                           khui_context_release(&ctx);\r
+                       }\r
+\r
+                        _end_task();\r
                         break;\r
+\r
                     }\r
                 }\r
 \r
@@ -564,6 +717,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
 \r
                     assert(nc->subtype == KMSG_CRED_NEW_CREDS);\r
 \r
+                    _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD);\r
+\r
                     code = TRUE; /* just has to be non-zero */\r
 \r
                     khui_cw_get_prompt_count(nc, &n_prompts);\r
@@ -581,16 +736,20 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                             break;\r
                     }\r
 \r
-                    if (idx >= n_prompts)\r
+                    if (idx >= n_prompts) {\r
+                        _reportf(L"Password prompt not found");\r
                         goto _skip_pwd;\r
+                    }\r
 \r
                     khui_cw_sync_prompt_values(nc);\r
 \r
                     cb = sizeof(wpwd);\r
                     if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,\r
                                                             wpwd,\r
-                                                            &cb)))\r
+                                                            &cb))) {\r
+                        _reportf(L"Failed to obtain password value");\r
                         goto _skip_pwd;\r
+                    }\r
 \r
                     UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);\r
 \r
@@ -605,8 +764,10 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                         char * atsign;\r
 \r
                         atsign = strchr(idname, '@');\r
-                        if (atsign == NULL)\r
+                        if (atsign == NULL) {\r
+                            _reportf(L"Identity name does not contain an '@'");\r
                             goto _skip_pwd;\r
+                        }\r
 \r
                         *atsign++ = 0;\r
 \r
@@ -629,6 +790,9 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
 \r
                     code = khm_krb4_kinit(aname, inst, realm,\r
                                           (long) d->lifetime, pwd);\r
+\r
+                    _reportf(L"khm_krb4_kinit returns code %d", code);\r
+\r
                 _skip_pwd:\r
 \r
                     if (code) {\r
@@ -649,6 +813,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                         }\r
                     }\r
                 }\r
+\r
+                _end_task();\r
             }\r
         }\r
         break;\r
index 23f913bd9b53018a7c47932a54ca9ac117824d8e..972ed4a0198d55b5ccdd98348fad712294e39c67 100644 (file)
@@ -200,7 +200,6 @@ krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
                                              &attr_id_krb5_flags))) {\r
                 rv = KHM_ERROR_UNKNOWN;\r
             }\r
-\r
         }\r
         break;\r
 \r
index 9f5d3c932ee2e5a665d32478b28470d215dd2a54..f31c4a4d3201e2b5f2504def333c94cbc2542fa5 100644 (file)
@@ -41,6 +41,7 @@
 #include<dynimport.h>\r
 \r
 #include<langres.h>\r
+#include<krb4_msgs.h>\r
 \r
 #define TYPENAME_ENCTYPE        L"EncType"\r
 #define TYPENAME_ADDR_LIST      L"AddrList"\r
index a07dc4b3089067eac5e14bfa7fad59ced86916bd..d9114e5b6c807ff89776220012bc073579b5d75b 100644 (file)
@@ -61,14 +61,14 @@ BEGIN
                     SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11\r
     CONTROL         "Obtain Kerberos 4 tickets",IDC_NCK4_OBTAIN,"Button",\r
                     BS_AUTOCHECKBOX | WS_TABSTOP,7,26,97,10\r
+    GROUPBOX        "Obtain Kerberos 4 tickets using",IDC_STATIC,7,43,286,72,\r
+                    WS_GROUP\r
     CONTROL         "Automatically determine method",IDC_NCK4_AUTO,"Button",\r
                     BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,23,58,119,10\r
     CONTROL         "Kerberos 5 to 4 translation",IDC_NCK4_K524,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,23,76,101,10\r
-    CONTROL         "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON | \r
-                    WS_TABSTOP,23,94,47,10\r
-    GROUPBOX        "Obtain Kerberos 4 tickets using",IDC_STATIC,7,43,286,72,\r
-                    WS_GROUP\r
+                    BS_AUTORADIOBUTTON,23,76,101,10\r
+    CONTROL         "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON,23,\r
+                    94,47,10\r
 END\r
 \r
 IDD_CFG_KRB4 DIALOGEX 0, 0, 255, 182\r
@@ -154,6 +154,15 @@ END
 #endif    // APSTUDIO_INVOKED\r
 \r
 \r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDI_PLUGIN              ICON                    "..\\..\\images\\plugin.ico"\r
+\r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
 // String Table\r
diff --git a/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc b/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc
new file mode 100644 (file)
index 0000000..9fa410f
--- /dev/null
@@ -0,0 +1,57 @@
+; // ** krb5_msgs.mc\r
+\r
+; /* Since .mc files can contain strings from any language, we define\r
+; all our messages in one file in the /lang/ directory instead of\r
+; language specific subdirectories. */\r
+\r
+; /* The type is set to (wchar_t *) because that's what we will be\r
+; feeding kherr_report() function. */\r
+\r
+; // MessageIdTypedef=LPWSTR\r
+\r
+; /* Severity values as defined in the message definition file are\r
+; currently ignored. */\r
+\r
+SeverityNames=(\r
+        Success=0x0\r
+)\r
+\r
+LanguageNames=(\r
+        English=0x409:MSG_ENU\r
+)\r
+\r
+OutputBase=16\r
+\r
+; /* Actual messages start here */\r
+\r
+MessageId=1\r
+Severity=Success\r
+SymbolicName=MSG_INITIAL\r
+Language=English\r
+Initial placeholder message\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_K4_NEW_CREDS\r
+Language=English\r
+Getting new Krb4 credentials for [%1!s!] using method [%2!d!]\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_K4_RENEW_CREDS\r
+Language=English\r
+Renewing Krb4 credentials for [%1!s!] using method [%2!d!]\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_K4_TRY_K524\r
+Language=English\r
+Trying Krb524 ...\r
+.\r
+\r
+MessageId=\r
+SymbolicName=MSG_K4_TRY_PASSWORD\r
+Language=English\r
+Trying Password ...\r
+.\r
+\r
index ceb2360075492665b0bc0d6b919de6e8faa39d56..2cf0de137c78f83bbcea818d8c59b839712ffdff 100644 (file)
@@ -1,6 +1,6 @@
 //{{NO_DEPENDENCIES}}\r
 // Microsoft Visual C++ generated include file.\r
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc\r
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc\r
 //\r
 #define IDS_UNK_ADDR_FMT                101\r
 #define IDS_KRB5_CREDTEXT_0             102\r
@@ -17,6 +17,8 @@
 #define IDD_CFG_ID_KRB4                 106\r
 #define IDS_TKT_ENCTYPE_LONG_DESC       107\r
 #define IDS_ERR_INVINST                 107\r
+#define IDI_ICON1                       107\r
+#define IDI_PLUGIN                      107\r
 #define IDS_ADDR_LIST_SHORT_DESC        108\r
 #define IDS_ERR_PWINTKT                 108\r
 #define IDS_ADDR_LIST_LONG_DESC         109\r
 #define IDC_NCK4_K524                   1035\r
 #define IDC_NCK4_AUTO                   1036\r
 #define IDC_CFG_GETTIX                  1037\r
-#define IDC_CHECK1                      1038\r
 \r
 // Next default values for new objects\r
 // \r
 #ifdef APSTUDIO_INVOKED\r
 #ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        107\r
+#define _APS_NEXT_RESOURCE_VALUE        108\r
 #define _APS_NEXT_COMMAND_VALUE         40001\r
 #define _APS_NEXT_CONTROL_VALUE         1039\r
 #define _APS_NEXT_SYMED_VALUE           101\r
index 3ca6b1cb9f7016c5a767c1f474d74e972bf4e5a0..90105f82727416b64e2ab9a6f388a8161bfcfadb 100644 (file)
 \r
 #include<netidmgr_intver.h>\r
 \r
+#ifndef LANGVER\r
+\r
+#define STR_FILEDESC "Kerberos 4 Plugin for NetIDMgr"\r
+#define STR_INTNAME  "krb4cred"\r
+#define STR_ORIGNAME "krb4cred.dll"\r
+\r
+#else\r
+\r
+#ifdef LANG_en_us\r
+\r
+#define STR_FILEDESC "English(US) language resources for the Keberos 4 plugin"\r
+#define STR_INTNAME  "krb4cred_en_us"\r
+#define STR_ORIGNAME "krb4cred_en_us.dll"\r
+\r
+#else\r
+\r
+#error Unknown langugae\r
+\r
+#endif\r
+\r
+#endif\r
+\r
 1 VERSIONINFO \r
         FILEVERSION     KH_VERSION_LIST\r
         PRODUCTVERSION  KH_VERSION_LIST\r
       BLOCK "040904b0"\r
       {\r
         VALUE "CompanyName",     KH_VERSTR_COMPANY_1033\r
-        VALUE "FileDescription", "Kerberos 4 plugin for NetIDMgr"\r
+        VALUE "FileDescription", STR_FILEDESC\r
         VALUE "FileVersion",     KH_VERSTR_VERSION_1033\r
-        VALUE "InternalName",    "krb4cred"\r
+        VALUE "InternalName",    STR_INTNAME\r
         VALUE "LegalCopyright",  KH_VERSTR_COPYRIGHT_1033\r
-        VALUE "OriginalFilename", "krb4cred.dll"\r
+        VALUE "OriginalFilename", STR_ORIGNAME\r
         VALUE "ProductName",     "NetIDMgr"\r
         VALUE "ProductVersion",  KH_VERSTR_PRODUCT_1033\r
 #ifdef KH_VERSTR_COMMENT_1033\r
         VALUE "Comment", KH_VERSTR_COMMENT_1033\r
 #endif\r
+#ifndef LANGVER\r
         VALUE NIMV_MODULE,       "MITKrb4"\r
         VALUE NIMV_PLUGINS,      "Krb4Cred"\r
         VALUE NIMV_APIVER,       KH_VERSION_STRINGAPI\r
         VALUE NIMV_SUPPORT,      "http://web.mit.edu/kerberos"\r
+#endif\r
       }\r
     }\r
 \r
@@ -62,5 +86,4 @@
     {\r
         VALUE "Translation", 0x409, 1200\r
     }\r
-\r
   }\r
index e0553d8461721ea3735aa0beeb0908ef3e83ba7c..67475ee010f6837626b1c280825032e47b66c57d 100644 (file)
-#\r
-# Copyright (c) 2004 Massachusetts Institute of Technology\r
-#\r
-# Permission is hereby granted, free of charge, to any person\r
-# obtaining a copy of this software and associated documentation files\r
-# (the "Software"), to deal in the Software without restriction,\r
-# including without limitation the rights to use, copy, modify, merge,\r
-# publish, distribute, sublicense, and/or sell copies of the Software,\r
-# and to permit persons to whom the Software is furnished to do so,\r
-# subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be\r
-# included in all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-# SOFTWARE.\r
-\r
-\r
-MODULE=plugins\krb5\r
-!include <../../config/Makefile.w32>\r
-\r
-DLLFILE=$(BINDIR)\krb5cred.dll\r
-\r
-LIBFILE=$(LIBDIR)\krb5cred.lib\r
-\r
-OBJFILES= \\r
-       $(LIBDIR)\dynimport.obj         \\r
-       $(LIBDIR)\krb5common.obj        \\r
-       $(OBJ)\krb5main.obj             \\r
-       $(OBJ)\datarep.obj              \\r
-       $(OBJ)\errorfuncs.obj           \\r
-       $(OBJ)\krb5plugin.obj           \\r
-       $(OBJ)\krb5props.obj            \\r
-       $(OBJ)\krb5newcreds.obj         \\r
-       $(OBJ)\krb5funcs.obj            \\r
-       $(OBJ)\krb5config.obj           \\r
-       $(OBJ)\krb5identpro.obj         \\r
-       $(OBJ)\krb5configdlg.obj        \\r
-       $(OBJ)\krb5configcc.obj         \\r
-       $(OBJ)\krb5configid.obj         \\r
-       $(OBJ)\krb5configids.obj\r
-\r
-LIBFILES= \\r
-       $(LIBDIR)\nidmgr32.lib          \\r
-       $(KFWLIBDIR)\loadfuncs.lib\r
-\r
-SDKLIBFILES=   \\r
-       netapi32.lib    \\r
-       shlwapi.lib     \\r
-       comctl32.lib\r
-\r
-MSGRESFILE=$(OBJ)\krb5_msgs.res\r
-\r
-VERRESFILE=$(OBJ)\version.res\r
-\r
-$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg\r
-       $(CCSV) $** $@\r
-\r
-$(DLLFILE): $(MSGRESFILE) $(VERRESFILE) $(OBJFILES)\r
-       $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)\r
-\r
-$(MSGRESFILE): $(OBJ)\krb5_msgs.rc\r
-\r
-$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc\r
-       $(MC2RC)\r
-\r
-all: mkdirs $(DLLFILE) lang\r
-\r
-lang::\r
-\r
-# Repeat this block as necessary redefining LANG for additional\r
-# languages.\r
-\r
-# Begin language block\r
-LANG=en_us\r
-\r
-LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll\r
-\r
-lang:: $(LANGDLL)\r
-\r
-$(LANGDLL): $(OBJ)\langres_$(LANG).res\r
-       $(DLLRESLINK)\r
-\r
-$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc\r
-       $(RC2RES)\r
-\r
-# End language block\r
-\r
-clean::\r
-!if defined(INCFILES)\r
-       $(RM) $(INCFILES)\r
-!endif\r
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb5
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb5cred.dll
+
+LIBFILE=$(LIBDIR)\krb5cred.lib
+
+OBJFILES= \
+       $(LIBDIR)\dynimport.obj         \
+       $(LIBDIR)\krb5common.obj        \
+       $(OBJ)\krb5main.obj             \
+       $(OBJ)\datarep.obj              \
+       $(OBJ)\errorfuncs.obj           \
+       $(OBJ)\krb5plugin.obj           \
+       $(OBJ)\krb5props.obj            \
+       $(OBJ)\krb5newcreds.obj         \
+       $(OBJ)\krb5funcs.obj            \
+       $(OBJ)\krb5config.obj           \
+       $(OBJ)\krb5identpro.obj         \
+       $(OBJ)\krb5configdlg.obj        \
+       $(OBJ)\krb5configcc.obj         \
+       $(OBJ)\krb5configid.obj         \
+       $(OBJ)\krb5configids.obj
+
+
+
+SDKLIBFILES=   \
+       netapi32.lib    \
+       shlwapi.lib     \
+       comctl32.lib
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+LIBFILES= \
+       $(LIBDIR)\nidmgr64.lib          \
+       $(KFWLIBDIR)\loadfuncs.lib
+!else
+SCLIB=
+LIBFILES= \
+       $(LIBDIR)\nidmgr32.lib          \
+       $(KFWLIBDIR)\loadfuncs.lib
+!endif
+
+MSGRESFILE=$(OBJ)\krb5_msgs.res
+
+VERRESFILE=$(OBJ)\version.res
+
+$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+       $(CCSV) $** $@
+
+$(DLLFILE):  $(OBJFILES) $(VERRESFILE) 
+       $(DLLGUILINK) $(MSGRESFILE) $(LIBFILES) $(SDKLIBFILES) $(SCLIB)
+
+$(MSGRESFILE): $(OBJ)\krb5_msgs.rc
+
+$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc
+       $(MC2RC)
+
+all: mkdirs $(MSGRESFILE) $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res
+       $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+       $(RC2RES)
+
+$(OBJ)\langres_ver_$(LANG).res: version.rc
+       $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $** 
+# End language block
+
+clean::
+!if defined(INCFILES)
+       $(RM) $(INCFILES)
+!endif
index 2c4036083340ea17fad423a4a57575953178c63f..97d629eb4ce9f7409857b97269bc9b81a1eef138 100644 (file)
 \r
 /* Data representation and related functions */\r
 \r
+#include<winsock2.h>\r
 #include<krbcred.h>\r
 #include<krb5.h>\r
 #include<kherror.h>\r
 #include<strsafe.h>\r
+#include<assert.h>\r
 \r
-khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *destbuf, khm_size *pcbdestbuf, khm_int32 flags)\r
+khm_int32 KHMAPI \r
+enctype_toString(const void * data, khm_size cbdata,\r
+                wchar_t *destbuf, khm_size *pcbdestbuf,\r
+                khm_int32 flags)\r
 {\r
     int resid = 0;\r
     int etype;\r
@@ -130,17 +135,90 @@ khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *d
     }\r
 }\r
 \r
-khm_int32 KHMAPI addr_list_toString(const void *d, khm_size cb_d, wchar_t *buf, khm_size *pcb_buf, khm_int32 flags)\r
+khm_int32 KHMAPI\r
+addr_list_comp(const void *d1, khm_size cb_d1,\r
+              const void *d2, khm_size cb_d2)\r
 {\r
-    /*TODO: implement this */\r
-    return KHM_ERROR_NOT_IMPLEMENTED;\r
+    if (cb_d1 < cb_d2)\r
+       return -1;\r
+    if (cb_d1 > cb_d2)\r
+       return 1;\r
+    return memcmp(d1, d2, cb_d1);\r
 }\r
 \r
-khm_int32 KHMAPI krb5flags_toString(const void *d, \r
-                                    khm_size cb_d, \r
-                                    wchar_t *buf, \r
-                                    khm_size *pcb_buf, \r
-                                    khm_int32 f)\r
+khm_int32 KHMAPI\r
+addr_list_toString(const void *d, khm_size cb_d,\r
+                  wchar_t *buf, khm_size *pcb_buf,\r
+                  khm_int32 flags)\r
+{\r
+    wchar_t tbuf[2048];\r
+    wchar_t * strpos;\r
+    khm_size cbleft;\r
+    size_t t;\r
+    k5_serial_address * addrs;\r
+\r
+    if (cb_d == 0 || d == NULL) {\r
+        tbuf[0] = L'\0';\r
+    } else {\r
+        addrs = (k5_serial_address *) d;\r
+\r
+        strpos = tbuf;\r
+        cbleft = sizeof(tbuf);\r
+        tbuf[0] = L'\0';\r
+\r
+        while (TRUE) {\r
+            if (cb_d < sizeof(*addrs) ||\r
+                addrs->magic != K5_SERIAL_ADDRESS_MAGIC ||\r
+                cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32))\r
+                break;\r
+\r
+            if (strpos != tbuf) {\r
+                if (FAILED(StringCbCatEx(strpos, cbleft, L"  ",\r
+                                         &strpos, &cbleft,\r
+                                         0)))\r
+                    break;\r
+            }\r
+\r
+#ifdef DEBUG\r
+            assert(*strpos == L'\0');\r
+#endif\r
+\r
+            one_addr(addrs, strpos, cbleft);\r
+\r
+           t = 0;\r
+           if (FAILED(StringCchLength(strpos,\r
+                                      cbleft / sizeof(wchar_t),\r
+                                      &t)))\r
+               break;\r
+\r
+           strpos += t;\r
+           cbleft -= t * sizeof(wchar_t);\r
+\r
+            t = sizeof(*addrs) + addrs->length - sizeof(khm_int32);\r
+            addrs = (k5_serial_address *) BYTEOFFSET(addrs, t);\r
+            cb_d -= t;\r
+        }\r
+    }\r
+\r
+    StringCbLength(tbuf, sizeof(tbuf), &t);\r
+\r
+    if (!buf || *pcb_buf < t) {\r
+        *pcb_buf = t;\r
+        return KHM_ERROR_TOO_LONG;\r
+    }\r
+\r
+    StringCbCopy(buf, *pcb_buf, tbuf);\r
+    *pcb_buf = t;\r
+\r
+    return KHM_ERROR_SUCCESS;\r
+}\r
+\r
+khm_int32 KHMAPI\r
+krb5flags_toString(const void *d, \r
+                  khm_size cb_d, \r
+                  wchar_t *buf, \r
+                  khm_size *pcb_buf, \r
+                  khm_int32 f)\r
 {\r
     wchar_t sbuf[32];\r
     int i = 0;\r
@@ -196,19 +274,42 @@ khm_int32 KHMAPI krb5flags_toString(const void *d,
     }\r
 }\r
 \r
-khm_int32 serialize_krb5_addresses(krb5_address ** a, void ** buf, size_t * pcbbuf)\r
+khm_int32\r
+serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf)\r
 {\r
-    /*TODO: implement this */\r
-    return KHM_ERROR_NOT_IMPLEMENTED;\r
-}\r
+    k5_serial_address * addr;\r
+    khm_size cb_req;\r
+    khm_size t;\r
+    khm_boolean overflow = FALSE;\r
+\r
+    addr = (k5_serial_address *) buf;\r
+    cb_req = 0;\r
+\r
+    for(; *a; a++) {\r
+        t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32);\r
+        cb_req += t;\r
+        if (cb_req < *pcbbuf) {\r
+            addr->magic = K5_SERIAL_ADDRESS_MAGIC;\r
+            addr->addrtype = (*a)->addrtype;\r
+            addr->length = (*a)->length;\r
+            memcpy(&addr->data, (*a)->contents, (*a)->length);\r
+\r
+            addr = (k5_serial_address *) BYTEOFFSET(addr, t);\r
+        } else {\r
+            overflow = TRUE;\r
+        }\r
+    }\r
 \r
-#if 0\r
+    *pcbbuf = cb_req;\r
 \r
-wchar_t * \r
-one_addr(krb5_address *a)\r
+    return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS;\r
+}\r
+\r
+void\r
+one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf)\r
 {\r
-    static wchar_t retstr[256];\r
-    struct hostent *h;\r
+    wchar_t retstr[256];\r
+    struct hostent *h = NULL;\r
     int no_resolve = 1;\r
 \r
     retstr[0] = L'\0';\r
@@ -227,43 +328,50 @@ one_addr(krb5_address *a)
         if (!no_resolve) {\r
 #ifdef HAVE_GETIPNODEBYADDR\r
             int err;\r
-            h = getipnodebyaddr(a->contents, a->length, af, &err);\r
+            h = getipnodebyaddr(&a->data, a->length, af, &err);\r
             if (h) {\r
                 StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);\r
                 freehostent(h);\r
             }\r
-#else\r
-            h = gethostbyaddr(a->contents, a->length, af);\r
+            else\r
+                h = gethostbyaddr(&a->data, a->length, af);\r
             if (h) {\r
                 StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);\r
             }\r
 #endif\r
             if (h)\r
-                return(retstr);\r
+                goto _copy_string;\r
         }\r
         if (no_resolve || !h) {\r
 #ifdef HAVE_INET_NTOP\r
             char buf[46];\r
-            const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf));\r
+            const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf));\r
             if (name) {\r
                 StringCbPrintf(retstr, sizeof(retstr), L"%S", name);\r
-                return;\r
+                goto _copy_string;\r
             }\r
 #else\r
             if (a->addrtype == ADDRTYPE_INET) {\r
+                khm_ui_4 addr = a->data;\r
                 StringCbPrintf(retstr, sizeof(retstr),\r
-                    L"%d.%d.%d.%d", a->contents[0], a->contents[1],\r
-                    a->contents[2], a->contents[3]);\r
-                return(retstr);\r
+                               L"%d.%d.%d.%d",\r
+                               (int) (addr & 0xff),\r
+                               (int) ((addr >> 8) & 0xff),\r
+                               (int) ((addr >> 16)& 0xff),\r
+                               (int) ((addr >> 24)& 0xff));\r
+                goto _copy_string;\r
             }\r
 #endif\r
         }\r
     }\r
+\r
     {\r
         wchar_t tmpfmt[128];\r
         LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t));\r
         StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype);\r
     }\r
-    return(retstr);\r
+\r
+ _copy_string:\r
+    StringCbCopy(buf, cbbuf, retstr);\r
 }\r
-#endif\r
+\r
index ac6771cb9c639d5c222769549001ef5f8db6ce10..eeb6970dade9f9e752e06790462f3551030f8321 100644 (file)
 #ifndef __KHIMAIRA_KRB_DATAREP_H\r
 #define __KHIMAIRA_KRB_DATAREP_H\r
 \r
+typedef struct tag_k5_serial_address {\r
+    khm_int32     magic;        /* should be K5_SERIAL_ADDRESS_MAGIC */\r
+    khm_int32     addrtype;     /* Address type. We only know what to\r
+                                   do with ADDRTYPE_INET and\r
+                                   ADDRTYPE_INET6 */\r
+    khm_size      length;       /* number of bytes of data in [data].\r
+                                   This should always be greater than\r
+                                   sizeof(khm_int32) */\r
+    khm_int32     data;         /* actually, &data is the beginning of\r
+                                   the data buffer that is [length]\r
+                                   bytes long. */\r
+} k5_serial_address;\r
 \r
-khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *destbuf, khm_size *pcbdestbuf, khm_int32 flags);\r
-khm_int32 KHMAPI addr_list_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);\r
-khm_int32 KHMAPI krb5flags_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);\r
-khm_int32 KHMAPI renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, khm_size * pcbsize);\r
+#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d\r
 \r
+khm_int32 KHMAPI\r
+enctype_toString(const void * data, khm_size cbdata,\r
+                 wchar_t *destbuf, khm_size *pcbdestbuf,\r
+                 khm_int32 flags);\r
 \r
+khm_int32 KHMAPI\r
+addr_list_comp(const void *d1, khm_size cb_d1,\r
+              const void *d2, khm_size cb_d2);\r
+\r
+khm_int32 KHMAPI\r
+addr_list_toString(const void *, khm_size, wchar_t *,\r
+                   khm_size *, khm_int32);\r
+\r
+khm_int32 KHMAPI\r
+krb5flags_toString(const void *, khm_size, wchar_t *,\r
+                   khm_size *, khm_int32);\r
+\r
+khm_int32 KHMAPI\r
+renew_for_cb(khm_handle cred, khm_int32 id, void * buffer,\r
+             khm_size * pcbsize);\r
+\r
+khm_int32\r
+serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf);\r
+\r
+void\r
+one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf);\r
 #endif\r
index 8cf89c7cd0ce1dfaf78e878bda53fba21be27fa2..0cb8b2ab7038bfeeb59c6c318248511493566d8d 100644 (file)
-/*\r
- * Copyright (c) 2005 Massachusetts Institute of Technology\r
- *\r
- * Permission is hereby granted, free of charge, to any person\r
- * obtaining a copy of this software and associated documentation\r
- * files (the "Software"), to deal in the Software without\r
- * restriction, including without limitation the rights to use, copy,\r
- * modify, merge, publish, distribute, sublicense, and/or sell copies\r
- * of the Software, and to permit persons to whom the Software is\r
- * furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be\r
- * included in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- */\r
-\r
-/* $Id$ */\r
-\r
-#include<krbcred.h>\r
-#include<krb5.h>\r
-#include<assert.h>\r
-#include<lm.h>\r
-#include<commctrl.h>\r
-\r
-#pragma warning(push)\r
-#pragma warning(disable: 4995)\r
-#include<shlwapi.h>\r
-#pragma warning(pop)\r
-\r
-\r
-typedef struct tag_k5_realm_kdc {\r
-    wchar_t       name[K5_MAXCCH_HOST];\r
-    khm_boolean   admin;        /* admin server? */\r
-    khm_boolean   master;       /* master kdc? */\r
-    khm_int32     flags;\r
-} k5_realm_kdc;\r
-\r
-#define K5_RKFLAG_DELETED    1\r
-#define K5_RKFLAG_NEW        2\r
-#define K5_RKFLAG_MOD_ADMIN  4\r
-#define K5_RKFLAG_MOD_MASTER 8\r
-\r
-typedef struct tag_k5_domain_map {\r
-    wchar_t       name[K5_MAXCCH_HOST]; /* name of host that maps to a\r
-                                           realm */\r
-    khm_int32     flags;\r
-} k5_domain_map;\r
-\r
-#define K5_DMFLAG_DELETED 1\r
-#define K5_DMFLAG_NEW     2\r
-\r
-typedef struct tag_k5_realm_data {\r
-    wchar_t       realm[K5_MAXCCH_REALM];\r
-    k5_realm_kdc  kdcs[K5_MAX_KDC];\r
-    khm_size      n_kdcs;\r
-    k5_domain_map domain_maps[K5_MAX_DOMAIN_MAPPINGS];\r
-    khm_size      n_domain_maps;\r
-\r
-    khm_int32     flags;\r
-} k5_realm_data;\r
-\r
-#define K5_RDFLAG_DELETED 1\r
-#define K5_RDFLAG_NEW     2\r
-#define K5_RDFLAG_MODIFED 4\r
-\r
-#define K5_REALMS_ALLOC_INCR 8\r
-\r
-typedef struct tag_k5_config_data {\r
-    wchar_t       def_realm[K5_MAXCCH_REALM];    /* default realm */\r
-\r
-    wchar_t       config_file[MAX_PATH]; /* path to configuration file */\r
-    khm_boolean   create_config_file; /* create config_file if missing? */\r
-    khm_boolean   inc_realms;   /* include full realm list in new\r
-                                   credentials dialog? */\r
-\r
-    /* [libdefaults] */\r
-    khm_boolean   dns_lookup_kdc;\r
-    khm_boolean   dns_lookup_realm;\r
-    khm_boolean   dns_fallback;\r
-\r
-    khm_boolean   noaddresses;\r
-\r
-    k5_lsa_import lsa_import;   /* import mslsa creds? */\r
-\r
-    /* [realms] */\r
-    k5_realm_data *realms;\r
-    khm_size      n_realms;\r
-    khm_size      nc_realms;\r
-    khm_size      c_realm;\r
-\r
-    khui_config_node node_main;\r
-    khui_config_node node_realm;\r
-\r
-    khm_int32     flags;\r
-} k5_config_data;\r
-\r
-#define K5_CDFLAG_MOD_DEF_REALM      0x00000001\r
-#define K5_CDFLAG_MOD_CONF_FILE      0x00000002\r
-#define K5_CDFLAG_MOD_DNS_LOOKUP_KDC 0x00000004\r
-#define K5_CDFLAG_MOD_DNS_LOOKUP_RLM 0x00000008\r
-#define K5_CDFLAG_MOD_DNS_FALLBACK   0x00000010\r
-#define K5_CDFLAG_MOD_NOADDRESSES    0x00000020\r
-#define K5_CDFLAG_MOD_LSA_IMPORT     0x00000040\r
-#define K5_CDFLAG_MOD_CREATE_CONF    0x00000080\r
-#define K5_CDFLAG_MOD_INC_REALMS     0x00000100\r
-#define K5_CDFLAG_MOD_REALMS         0x00001000\r
-\r
-static const char *const conf_yes[] = {\r
-    "y", "yes", "true", "t", "1", "on",\r
-    0,\r
-};\r
-\r
-static const char *const conf_no[] = {\r
-    "n", "no", "false", "nil", "0", "off",\r
-    0,\r
-};\r
-\r
-int\r
-k5_parse_boolean(const char *s)\r
-{\r
-    const char *const *p;\r
-\r
-    for(p=conf_yes; *p; p++) {\r
-        if (!stricmp(*p,s))\r
-            return 1;\r
-    }\r
-\r
-    for(p=conf_no; *p; p++) {\r
-        if (!stricmp(*p,s))\r
-            return 0;\r
-    }\r
-\r
-    /* Default to "no" */\r
-    return 0;\r
-}\r
-\r
-void\r
-k5_init_config_data(k5_config_data * d) {\r
-    ZeroMemory(d, sizeof(*d));\r
-}\r
-\r
-void\r
-k5_free_config_data(k5_config_data * d) {\r
-    if (d->realms)\r
-        PFREE(d->realms);\r
-\r
-    k5_init_config_data(d);\r
-}\r
-\r
-static void\r
-k5_assert_n_realms(k5_config_data * d, khm_size n) {\r
-    khm_size nc_realms;\r
-\r
-    if (n <= d->nc_realms)\r
-        return;\r
-\r
-    nc_realms = UBOUNDSS(n, K5_REALMS_ALLOC_INCR, K5_REALMS_ALLOC_INCR);\r
-    assert(nc_realms > d->nc_realms);\r
-\r
-    d->realms = PREALLOC(d->realms, nc_realms * sizeof(*(d->realms)));\r
-    d->nc_realms = nc_realms;\r
-\r
-    ZeroMemory(&d->realms[d->n_realms],\r
-               (d->nc_realms - d->n_realms) * sizeof(*(d->realms)));\r
-}\r
-\r
-void\r
-k5_purge_config_data(k5_config_data * d,\r
-                     khm_boolean purge_realms,\r
-                     khm_boolean purge_kdcs,\r
-                     khm_boolean purge_dmap) {\r
-    khm_size r;\r
-    khm_size k;\r
-    khm_size m;\r
-\r
-    for (r=0; r < d->n_realms; r++) {\r
-        if (purge_realms &&\r
-            (d->realms[r].flags & K5_RDFLAG_NEW) &&\r
-            (d->realms[r].flags & K5_RDFLAG_DELETED)) {\r
-\r
-            if (d->n_realms > r+1)\r
-                MoveMemory(&d->realms[r], &d->realms[r+1],\r
-                           sizeof(d->realms[0]) * (d->n_realms - (r+1)));\r
-            r--;\r
-            d->n_realms--;\r
-            continue;\r
-        }\r
-\r
-        for (k=0; k < d->realms[r].n_kdcs; k++) {\r
-            if (purge_kdcs &&\r
-                (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&\r
-                (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {\r
-                if (d->realms[r].n_kdcs > k + 1)\r
-                    MoveMemory(&d->realms[r].kdcs[k],\r
-                               &d->realms[r].kdcs[k+1],\r
-                               sizeof(d->realms[0].kdcs[0]) *\r
-                               (d->realms[r].n_kdcs - (k+1)));\r
-                k--;\r
-                d->realms[r].n_kdcs--;\r
-                continue;\r
-            }\r
-        }\r
-\r
-        if (K5_MAX_KDC > k+1)\r
-            ZeroMemory(&d->realms[r].kdcs[k],\r
-                       sizeof(d->realms[0].kdcs[0]) *\r
-                       (K5_MAX_KDC - (k + 1)));\r
-\r
-        for (m=0; m < d->realms[r].n_domain_maps; m++) {\r
-            if (purge_dmap &&\r
-                (d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&\r
-                (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) {\r
-                if (d->realms[r].n_domain_maps > m + 1)\r
-                    MoveMemory(&d->realms[r].domain_maps[m],\r
-                               &d->realms[r].domain_maps[m+1],\r
-                               sizeof(d->realms[0].domain_maps[0]) *\r
-                               (d->realms[r].n_domain_maps - (m+1)));\r
-                m--;\r
-                d->realms[r].n_domain_maps--;\r
-                continue;\r
-            }\r
-        }\r
-\r
-        if (K5_MAX_DOMAIN_MAPPINGS > m+1)\r
-            ZeroMemory(&d->realms[r].domain_maps[m],\r
-                       sizeof(d->realms[0].domain_maps[0]) *\r
-                       (K5_MAX_DOMAIN_MAPPINGS - (m+1)));\r
-    }\r
-\r
-    if (d->nc_realms > r + 1)\r
-        ZeroMemory(&d->realms[r],\r
-                   sizeof(d->realms[0]) *\r
-                   (d->nc_realms - (r + 1)));\r
-}\r
-\r
-static khm_boolean\r
-k5_is_profile_loaded(void) {\r
-#ifdef DEBUG\r
-    assert(pprofile_init);\r
-    assert(pprofile_get_subsection_names);\r
-    assert(pprofile_get_values);\r
-    assert(pprofile_get_string);\r
-    assert(pprofile_get_relation_names);\r
-    assert(pprofile_free_list);\r
-    assert(pprofile_release_string);\r
-    assert(pprofile_release);\r
-    assert(pprofile_clear_relation);\r
-    assert(pprofile_add_relation);\r
-    assert(pprofile_update_relation);\r
-    assert(pprofile_flush);\r
-#endif\r
-\r
-    if (!pprofile_init ||\r
-        !pprofile_get_subsection_names ||\r
-        !pprofile_get_values ||\r
-        !pprofile_get_string ||\r
-        !pprofile_get_relation_names ||\r
-        !pprofile_free_list ||\r
-        !pprofile_release_string ||\r
-        !pprofile_release ||\r
-        !pprofile_clear_relation ||\r
-        !pprofile_add_relation ||\r
-        !pprofile_update_relation ||\r
-        !pprofile_flush)\r
-\r
-        return FALSE;\r
-\r
-    return TRUE;\r
-}\r
-\r
-void\r
-k5_read_config_data(k5_config_data * d) {\r
-    wchar_t * defrealm;\r
-    char config_file[MAX_PATH];\r
-    profile_t profile = NULL;\r
-    const char *filenames[2];\r
-    long rv;\r
-    khm_size s;\r
-\r
-    if (!k5_is_profile_loaded())\r
-        return;\r
-\r
-    defrealm = khm_krb5_get_default_realm();\r
-\r
-    if (defrealm) {\r
-        StringCbCopy(d->def_realm, sizeof(d->def_realm), defrealm);\r
-        PFREE(defrealm);\r
-    } else {\r
-        StringCbCopy(d->def_realm, sizeof(d->def_realm), L"");\r
-    }\r
-\r
-    khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));\r
-\r
-    AnsiStrToUnicode(d->config_file, sizeof(d->config_file), config_file);\r
-\r
-    filenames[0] = config_file;\r
-    filenames[1] = NULL;\r
-\r
-    rv = pprofile_init(filenames, &profile);\r
-\r
-    if (!rv) {\r
-        const char * sec_realms[] = { "realms", NULL };\r
-        const char * sec_domain_realm[] = { "domain_realm", NULL };\r
-        char ** sections;\r
-        char ** dr_from;\r
-        char * boolv;\r
-\r
-        /* first fish out a few values from [libdefaults] */\r
-\r
-        rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc",\r
-                                 NULL, NULL, &boolv);\r
-        if (!rv && boolv) {\r
-            d->dns_lookup_kdc = k5_parse_boolean(boolv);\r
-            pprofile_release_string(boolv);\r
-        } else\r
-            d->dns_lookup_kdc = FALSE;\r
-\r
-        rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm",\r
-                                 NULL, NULL, &boolv);\r
-        if (!rv && boolv) {\r
-            d->dns_lookup_realm = k5_parse_boolean(boolv);\r
-            pprofile_release_string(boolv);\r
-        } else\r
-            d->dns_lookup_realm = FALSE;\r
-\r
-        rv = pprofile_get_string(profile, "libdefaults", "dns_fallback",\r
-                                 NULL, NULL, &boolv);\r
-        if (!rv && boolv) {\r
-            d->dns_fallback = k5_parse_boolean(boolv);\r
-            pprofile_release_string(boolv);\r
-        } else\r
-            d->dns_fallback = FALSE;\r
-\r
-        rv = pprofile_get_string(profile, "libdefaults", "noaddresses",\r
-                                 NULL, NULL, &boolv);\r
-        if (!rv && boolv) {\r
-            d->noaddresses = k5_parse_boolean(boolv);\r
-            pprofile_release_string(boolv);\r
-        } else\r
-            d->noaddresses = TRUE;\r
-\r
-        /* now we look at the [realms] section */\r
-        rv = pprofile_get_subsection_names(profile, sec_realms, &sections);\r
-\r
-        /* what? no realms? whatever */\r
-        if (rv) goto _skip_realms;\r
-\r
-        /* get a count first */\r
-        for (s=0; sections[s] && sections[s][0]; s++);\r
-\r
-        k5_assert_n_realms(d, s);\r
-        d->n_realms = s;\r
-\r
-        /* now go through each and fish out the kdcs, admin_server\r
-           and master_kdc. */\r
-        for (s=0; sections[s] && sections[s][0]; s++) {\r
-            const char * sec_kdcs[] = \r
-                { "realms", sections[s], "kdc", NULL };\r
-\r
-            const char * sec_admin[] =\r
-                { "realms", sections[s], "admin_server", NULL };\r
-\r
-            const char * sec_master[] =\r
-                { "realms", sections[s], "master_kdc", NULL };\r
-\r
-            char ** values;\r
-\r
-            AnsiStrToUnicode(d->realms[s].realm, sizeof(d->realms[s].realm),\r
-                             sections[s]);\r
-            d->realms[s].n_kdcs = 0;\r
-            d->realms[s].n_domain_maps = 0;\r
-\r
-            rv = pprofile_get_values(profile, sec_kdcs, &values);\r
-            if (!rv) {\r
-                khm_size i;\r
-\r
-                for (i=0 ; values[i] && values[i][0] && i < K5_MAX_KDC; i++) {\r
-                    AnsiStrToUnicode(d->realms[s].kdcs[i].name,\r
-                                     sizeof(d->realms[s].kdcs[i].name),\r
-                                     values[i]);\r
-\r
-                }\r
-                d->realms[s].n_kdcs = i;\r
-\r
-                pprofile_free_list(values);\r
-            }\r
-\r
-            rv = pprofile_get_values(profile, sec_admin, &values);\r
-            if (!rv) {\r
-                khm_size i;\r
-                khm_size j;\r
-                wchar_t kdc_name[K5_MAXCCH_HOST];\r
-\r
-                for (i=0; values[i] && values[i][0]; i++) {\r
-                    AnsiStrToUnicode(kdc_name,\r
-                                     sizeof(kdc_name), values[i]);\r
-\r
-                    for (j=0; j < d->realms[s].n_kdcs; j++)\r
-                        if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))\r
-                            break;\r
-\r
-                    if (j < d->realms[s].n_kdcs) {\r
-                        d->realms[s].kdcs[j].admin = TRUE;\r
-                    } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {\r
-                        j = d->realms[s].n_kdcs;\r
-                        StringCbCopy(d->realms[s].kdcs[j].name,\r
-                                     sizeof(d->realms[s].kdcs[j].name),\r
-                                     kdc_name);\r
-                        d->realms[s].kdcs[j].admin = TRUE;\r
-                        d->realms[s].n_kdcs ++;\r
-                    }\r
-                }\r
-                pprofile_free_list(values);\r
-            }\r
-\r
-            rv = pprofile_get_values(profile, sec_master, &values);\r
-            if (!rv) {\r
-                khm_size i;\r
-                khm_size j;\r
-                wchar_t kdc_name[K5_MAXCCH_HOST];\r
-\r
-                for (i=0; values[i] && values[i][0]; i++) {\r
-                    AnsiStrToUnicode(kdc_name, sizeof(kdc_name), values[i]);\r
-\r
-                    for (j=0; j < d->realms[s].n_kdcs; j++)\r
-                        if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))\r
-                            break;\r
-\r
-                    if (j < d->realms[s].n_kdcs) {\r
-                        d->realms[s].kdcs[j].master = TRUE;\r
-                    } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {\r
-                        j = d->realms[s].n_kdcs;\r
-                        StringCbCopy(d->realms[s].kdcs[j].name,\r
-                                     sizeof(d->realms[s].kdcs[j].name),\r
-                                     kdc_name);\r
-                        d->realms[s].kdcs[j].master = TRUE;\r
-                        d->realms[s].n_kdcs ++;\r
-                    }\r
-                }\r
-\r
-                pprofile_free_list(values);\r
-            }\r
-        }\r
-        pprofile_free_list(sections);\r
-\r
-    _skip_realms:\r
-\r
-        rv = pprofile_get_relation_names(profile, sec_domain_realm, &dr_from);\r
-        if (!rv) {\r
-            khm_size i;\r
-            khm_size j;\r
-            char * dr_to;\r
-            wchar_t wdr_from[K5_MAXCCH_HOST];\r
-            wchar_t wdr_to[K5_MAXCCH_HOST];\r
-\r
-            for (i=0; dr_from[i] && dr_from[i][0]; i++) {\r
-                AnsiStrToUnicode(wdr_from, sizeof(wdr_from), dr_from[i]);\r
-\r
-                rv = pprofile_get_string(profile, "domain_realm", dr_from[i],\r
-                                         NULL, NULL, &dr_to);\r
-\r
-                if (rv || !dr_to)\r
-                    continue;\r
-\r
-                AnsiStrToUnicode(wdr_to, sizeof(wdr_to), dr_to);\r
-\r
-                for (j=0; j < d->n_realms; j++) {\r
-                    if (!wcsicmp(wdr_to, d->realms[j].realm))\r
-                        break;\r
-                }\r
-\r
-                if (j >= d->n_realms) {\r
-                    j = d->n_realms;\r
-                    k5_assert_n_realms(d, j + 1);\r
-\r
-                    StringCbCopy(d->realms[j].realm,\r
-                                 sizeof(d->realms[j].realm),\r
-                                 wdr_to);\r
-                    d->realms[j].n_kdcs = 0;\r
-                    d->realms[j].n_domain_maps = 0;\r
-\r
-                    d->n_realms++;\r
-                }\r
-\r
-                if (d->realms[j].n_domain_maps < K5_MAX_DOMAIN_MAPPINGS) {\r
-                    khm_size k;\r
-\r
-                    k = d->realms[j].n_domain_maps;\r
-\r
-                    StringCbCopy(d->realms[j].domain_maps[k].name,\r
-                                 sizeof(d->realms[j].domain_maps[k].name),\r
-                                 wdr_from);\r
-\r
-                    d->realms[j].n_domain_maps++;\r
-                }\r
-\r
-                pprofile_release_string(dr_to);\r
-            }\r
-            pprofile_free_list(dr_from);\r
-        }\r
-        pprofile_release(profile);\r
-    }\r
-\r
-    {\r
-        khm_int32 t;\r
-\r
-        /* last, read the MSLSA import setting */\r
-        if (KHM_SUCCEEDED(khc_read_int32(csp_params,\r
-                                         L"MsLsaImport", &t))) {\r
-            d->lsa_import = t;\r
-        } else {\r
-            d->lsa_import = K5_LSAIMPORT_ALWAYS;\r
-        }\r
-\r
-        if (KHM_SUCCEEDED(khc_read_int32(csp_params,\r
-                                         L"UseFullRealmList", &t))) {\r
-            d->inc_realms = !!t;\r
-        } else {\r
-            d->inc_realms = TRUE;\r
-        }\r
-    }\r
-\r
-    d->flags = 0;\r
-}\r
-\r
-void\r
-k5_write_config_data(k5_config_data * d) {\r
-    char astr[MAX_PATH * 2];\r
-    char config_file[MAX_PATH];\r
-    profile_t profile = NULL;\r
-    const char *filenames[2];\r
-    long rv;\r
-    khm_size s;\r
-\r
-    if (d->flags == 0)\r
-        return;\r
-\r
-    if (!k5_is_profile_loaded())\r
-        return;\r
-\r
-    if (d->flags & K5_CDFLAG_MOD_DEF_REALM) {\r
-        if (SUCCEEDED(StringCbLength(d->def_realm,\r
-                                     sizeof(d->def_realm), &s)) &&\r
-            s > 0) {\r
-            khm_krb5_set_default_realm(d->def_realm);\r
-        }\r
-    }\r
-\r
-    /* write the MSLSA import setting */\r
-    if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {\r
-        khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);\r
-    }\r
-\r
-    if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {\r
-        khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);\r
-    }\r
-\r
-    if (!(d->flags & \r
-          (K5_CDFLAG_MOD_CONF_FILE |\r
-           K5_CDFLAG_MOD_DNS_FALLBACK |\r
-           K5_CDFLAG_MOD_DNS_LOOKUP_RLM |\r
-           K5_CDFLAG_MOD_DNS_LOOKUP_KDC |\r
-           K5_CDFLAG_MOD_NOADDRESSES |\r
-           K5_CDFLAG_MOD_CREATE_CONF |\r
-           K5_CDFLAG_MOD_REALMS))) {\r
-\r
-        d->flags = 0;\r
-        return;\r
-\r
-    }\r
-\r
-    khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));\r
-\r
-    UnicodeStrToAnsi(astr, sizeof(astr), d->config_file);\r
-\r
-    if (stricmp(config_file, astr)) {\r
-        assert(FALSE);\r
-    }\r
-\r
-    filenames[0] = config_file;\r
-    filenames[1] = NULL;\r
-\r
-    rv = pprofile_init(filenames, &profile);\r
-\r
-#if FAILOVER_TO_TEMPORARY_FILE\r
-    if (rv) {\r
-        char temp_file[MAX_PATH];\r
-\r
-        khm_krb5_get_temp_profile_file(temp_file,\r
-                                       ARRAYLENGTH(temp_file));\r
-\r
-        filenames[0] = temp_file;\r
-\r
-        rv = pprofile_init(filenames, &profile);\r
-\r
-            ?? TODO: Also warn if we are doing this\r
-    }\r
-#endif\r
-\r
-\r
-    if (!rv) {\r
-        const char * sec_realms[] = { "realms", NULL };\r
-        const char * sec_domain_realm[] = { "domain_realm", NULL };\r
-        const char * sec_libdefaults[] = { "libdefaults", NULL, NULL };\r
-        khm_size r;\r
-\r
-        if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_KDC) {\r
-\r
-            sec_libdefaults[1] = "dns_lookup_kdc";\r
-\r
-            pprofile_clear_relation(profile, sec_libdefaults);\r
-\r
-            rv = pprofile_add_relation(profile, sec_libdefaults,\r
-                                       (d->dns_lookup_kdc)?\r
-                                       conf_yes[0]:\r
-                                       conf_no[0]);\r
-        }\r
-\r
-\r
-        if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {\r
-\r
-            sec_libdefaults[1] = "dns_lookup_realm";\r
-\r
-            pprofile_clear_relation(profile, sec_libdefaults);\r
-\r
-            rv = pprofile_add_relation(profile, sec_libdefaults,\r
-                                       (d->dns_lookup_realm)?\r
-                                       conf_yes[0]:\r
-                                       conf_no[0]);\r
-\r
-        }\r
-\r
-        if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {\r
-\r
-            sec_libdefaults[1] = "dns_fallback";\r
-\r
-            pprofile_clear_relation(profile, sec_libdefaults);\r
-\r
-            rv = pprofile_add_relation(profile, sec_libdefaults,\r
-                                       (d->dns_fallback)?\r
-                                       conf_yes[0]:\r
-                                       conf_no[0]);\r
-        }\r
-\r
-        if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {\r
-\r
-            sec_libdefaults[1] = "noaddresses";\r
-\r
-            pprofile_clear_relation(profile, sec_libdefaults);\r
-\r
-            rv = pprofile_add_relation(profile, sec_libdefaults,\r
-                                       (d->noaddresses)?\r
-                                       conf_yes[0]:\r
-                                       conf_no[0]);\r
-        }\r
-\r
-        /* now we look at the [realms] section */\r
-\r
-        for (r=0; r < d->n_realms; r++) {\r
-            char realm[K5_MAXCCH_REALM];\r
-            char host[K5_MAXCCH_HOST];\r
-\r
-            const char * sec_kdcs[] = \r
-                { "realms", realm, "kdc", NULL };\r
-\r
-            const char * sec_admin[] =\r
-                { "realms", realm, "admin_server", NULL };\r
-\r
-            const char * sec_master[] =\r
-                { "realms", realm, "master_kdc", NULL };\r
-\r
-            const char * sec_domain_map[] =\r
-                { "domain_realm", host, NULL };\r
-\r
-            char ** values;\r
-\r
-            UnicodeStrToAnsi(realm, sizeof(realm),\r
-                             d->realms[r].realm);\r
-\r
-            if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&\r
-                (d->realms[r].flags & K5_RDFLAG_NEW)) {\r
-\r
-                khm_size k;\r
-                khm_size m;\r
-\r
-                /* this is a new realm */\r
-\r
-                for (k=0; k < d->realms[r].n_kdcs; k++) {\r
-                    if (!(d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {\r
-                        UnicodeStrToAnsi(host, sizeof(host),\r
-                                         d->realms[r].kdcs[k].name);\r
-\r
-                        if (d->realms[r].kdcs[k].master)\r
-                            pprofile_add_relation(profile, sec_master,\r
-                                                  host);\r
-                        else\r
-                            pprofile_add_relation(profile, sec_kdcs,\r
-                                                  host);\r
-\r
-                        if (d->realms[r].kdcs[k].admin)\r
-                            pprofile_add_relation(profile, sec_admin,\r
-                                                  host);\r
-                    }\r
-                }\r
-\r
-                for (m=0; m < d->realms[r].n_domain_maps; m++) {\r
-\r
-                    UnicodeStrToAnsi(host, sizeof(host),\r
-                                     d->realms[r].domain_maps[m].name);\r
-\r
-                    if ((d->realms[r].domain_maps[m].flags &\r
-                         K5_DMFLAG_DELETED) &&\r
-                        !(d->realms[r].domain_maps[m].flags &\r
-                          K5_DMFLAG_NEW))\r
-                        pprofile_clear_relation(profile, sec_domain_map);\r
-                    else if (!(d->realms[r].domain_maps[m].flags &\r
-                               K5_DMFLAG_DELETED) &&\r
-                             (d->realms[r].domain_maps[m].flags &\r
-                              K5_DMFLAG_NEW))\r
-                        pprofile_add_relation(profile, sec_domain_map,\r
-                                              realm);\r
-                }\r
-            } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&\r
-                       !(d->realms[r].flags & K5_RDFLAG_NEW)) {\r
-\r
-                const char * sec_all[] =\r
-                    { "realms", realm, NULL, NULL };\r
-                khm_size v;\r
-\r
-                /* this realm should be deleted */\r
-\r
-                rv = pprofile_get_relation_names(profile, sec_all,\r
-                                                 &values);\r
-                if (!rv) {\r
-                    for (v=0; values[v] && values[v][0]; v++) {\r
-                        sec_all[2] = values[v];\r
-                        pprofile_clear_relation(profile, sec_all);\r
-                    }\r
-                    pprofile_free_list(values);\r
-                }\r
-\r
-                rv = pprofile_get_relation_names(profile, sec_domain_realm,\r
-                                                 &values);\r
-                if (!rv) {\r
-                    char * maprealm;\r
-\r
-                    for (v=0; values[v] && values[v][0]; v++) {\r
-\r
-                        rv = pprofile_get_string(profile, "domain_realm",\r
-                                                 values[v], NULL, NULL,\r
-                                                 &maprealm);\r
-\r
-                        if (!rv) {\r
-                            if (!strcmp(maprealm, realm)) {\r
-                                StringCbCopyA(host, sizeof(host), \r
-                                              values[v]);\r
-                                pprofile_clear_relation(profile, \r
-                                                        sec_domain_map);\r
-                            }\r
-                            pprofile_release_string(maprealm);\r
-                        }\r
-                    }\r
-\r
-                    pprofile_free_list(values);\r
-                }\r
-            } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {\r
-                khm_size k;\r
-                khm_size m;\r
-\r
-                /* same as before.  check if we have to update the kdc\r
-                   list or the domain_realm mappings */\r
-\r
-                for (k=0; k < d->realms[r].n_kdcs; k++) {\r
-                    UnicodeStrToAnsi(host, sizeof(host),\r
-                                     d->realms[r].kdcs[k].name);\r
-                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED) {\r
-                        pprofile_update_relation(profile, sec_kdcs,\r
-                                                 host, NULL);\r
-                        pprofile_update_relation(profile, sec_admin,\r
-                                                 host, NULL);\r
-                        pprofile_update_relation(profile, sec_master,\r
-                                                 host, NULL);\r
-\r
-                        continue;\r
-                    }\r
-\r
-                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) {\r
-                        if (d->realms[r].kdcs[k].master)\r
-                            pprofile_add_relation(profile, sec_master,\r
-                                                  host);\r
-                        else\r
-                            pprofile_add_relation(profile, sec_kdcs,\r
-                                                  host);\r
-\r
-                        if (d->realms[r].kdcs[k].admin)\r
-                            pprofile_add_relation(profile, sec_admin,\r
-                                                  host);\r
-                        continue;\r
-                    }\r
-\r
-                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) {\r
-                        if (!d->realms[r].kdcs[k].master) {\r
-                            pprofile_add_relation(profile, sec_kdcs,\r
-                                                  host);\r
-                            pprofile_update_relation(profile, sec_master,\r
-                                                     host, NULL);\r
-                        } else {\r
-                            pprofile_add_relation(profile, sec_master,\r
-                                                  host);\r
-                            pprofile_update_relation(profile, sec_kdcs,\r
-                                                     host, NULL);\r
-                        }\r
-                    }\r
-\r
-                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_ADMIN) {\r
-                        if (d->realms[r].kdcs[k].admin)\r
-                            pprofile_add_relation(profile, sec_admin,\r
-                                                  host);\r
-                        else\r
-                            pprofile_update_relation(profile, sec_admin,\r
-                                                     host, NULL);\r
-                    }\r
-                }\r
-\r
-                for (m=0; m < d->realms[r].n_domain_maps; m++) {\r
-\r
-                    UnicodeStrToAnsi(host, sizeof(host),\r
-                                     d->realms[r].domain_maps[m].name);\r
-\r
-                    if ((d->realms[r].domain_maps[m].flags &\r
-                         K5_DMFLAG_DELETED) &&\r
-                        !(d->realms[r].domain_maps[m].flags &\r
-                          K5_DMFLAG_NEW))\r
-                        pprofile_clear_relation(profile, sec_domain_map);\r
-                    else if (!(d->realms[r].domain_maps[m].flags &\r
-                               K5_DMFLAG_DELETED) &&\r
-                             (d->realms[r].domain_maps[m].flags &\r
-                              K5_DMFLAG_NEW))\r
-                        pprofile_add_relation(profile, sec_domain_map,\r
-                                              realm);\r
-                }\r
-            }\r
-        }\r
-\r
-        rv = pprofile_flush(profile);\r
-\r
-        pprofile_release(profile);\r
-    }\r
-\r
-    if (rv) {\r
-        khui_alert * alert;\r
-        wchar_t title[KHUI_MAXCCH_TITLE];\r
-        wchar_t fmsg[KHUI_MAXCCH_MESSAGE];\r
-        wchar_t msg[KHUI_MAXCCH_MESSAGE];\r
-        wchar_t sugg[KHUI_MAXCCH_SUGGESTION];\r
-\r
-        LoadString(hResModule, IDS_K5ERR_CANTWRITEPROFILE,\r
-                   title, ARRAYLENGTH(title));\r
-        if (rv)\r
-            LoadString(hResModule, IDS_K5ERR_PROFNOWRITE,\r
-                       fmsg, ARRAYLENGTH(fmsg));\r
-\r
-        LoadString(hResModule, IDS_K5ERR_PROFSUGGEST,\r
-                   sugg, ARRAYLENGTH(sugg));\r
-\r
-        StringCbPrintf(msg, sizeof(msg), fmsg, config_file);\r
-\r
-        khui_alert_create_empty(&alert);\r
-        khui_alert_set_severity(alert, (rv)?KHERR_ERROR:KHERR_WARNING);\r
-        khui_alert_set_title(alert, title);\r
-        khui_alert_set_message(alert, msg);\r
-        khui_alert_set_suggestion(alert, sugg);\r
-        \r
-        khui_alert_show(alert);\r
-    }\r
-\r
-    d->flags = 0;\r
-}\r
-\r
-/* actual dialog stuff */\r
-\r
-#define IDX_NORMAL   1\r
-#define IDX_MODIFIED 2\r
-#define IDX_NEW      3\r
-#define IDX_DELETED  4\r
-\r
-static k5_config_data k5_config_dlg_data;\r
-static khm_boolean    k5_dlg_data_valid = FALSE;\r
-\r
-INT_PTR CALLBACK \r
-k5_config_dlgproc(HWND hwnd,\r
-                  UINT uMsg,\r
-                  WPARAM wParam,\r
-                  LPARAM lParam) {\r
-    switch(uMsg) {\r
-    case WM_INITDIALOG:\r
-        {\r
-            HWND hw;\r
-            khm_size i;\r
-            k5_config_data * d;\r
-\r
-            wchar_t * t;\r
-            wchar_t importopts[256];\r
-            WKSTA_INFO_100 * winfo100;\r
-\r
-#ifdef DEBUG\r
-            assert(!k5_dlg_data_valid);\r
-#endif\r
-\r
-            k5_init_config_data(&k5_config_dlg_data);\r
-            k5_read_config_data(&k5_config_dlg_data);\r
-\r
-            k5_dlg_data_valid = TRUE;\r
-\r
-            d = &k5_config_dlg_data;\r
-\r
-            d->node_main = (khui_config_node) lParam;\r
-\r
-            CheckDlgButton(hwnd, IDC_CFG_INCREALMS,\r
-                           (d->inc_realms)? BST_CHECKED: BST_UNCHECKED);\r
-\r
-            hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM);\r
-#ifdef DEBUG\r
-            assert(hw);\r
-#endif\r
-\r
-            SendMessage(hw, CB_RESETCONTENT, 0, 0);\r
-\r
-            for (i=0; i < d->n_realms; i++) {\r
-                SendMessage(hw, CB_ADDSTRING, 0,\r
-                            (LPARAM) d->realms[i].realm);\r
-            }\r
-\r
-            SendMessage(hw, CB_SELECTSTRING, -1,\r
-                        (LPARAM) d->def_realm);\r
-\r
-            SetDlgItemText(hwnd, IDC_CFG_CFGFILE, d->config_file);\r
-\r
-            /* hostname/domain */\r
-            if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) {\r
-                SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername);\r
-                SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup);\r
-                NetApiBufferFree(winfo100);\r
-            }\r
-\r
-            /* and the import ticket options */\r
-            LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS,\r
-                       importopts, ARRAYLENGTH(importopts));\r
-\r
-            hw = GetDlgItem(hwnd, IDC_CFG_IMPORT);\r
-#ifdef DEBUG\r
-            assert(hw);\r
-#endif\r
-            SendMessage(hw, CB_RESETCONTENT, 0, 0);\r
-\r
-            for (t=importopts; \r
-                 t && *t && *t != L' ' &&\r
-                     t < importopts + ARRAYLENGTH(importopts);\r
-                 t = multi_string_next(t)) {\r
-\r
-                SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);\r
-            }\r
-\r
-            SendMessage(hw, CB_SETCURSEL, 0, d->lsa_import);\r
-            t = importopts;\r
-            SendMessage(hw, CB_GETLBTEXT, d->lsa_import,(LPARAM) t);\r
-            SendMessage(hw, CB_SELECTSTRING, -1, (LPARAM) t);\r
-        }\r
-        break;\r
-\r
-    case WM_COMMAND:\r
-        {\r
-            k5_config_data * d;\r
-\r
-            d = &k5_config_dlg_data;\r
-\r
-            if (wParam == MAKEWPARAM(IDC_CFG_IMPORT, CBN_SELCHANGE)) {\r
-                int idx;\r
-                int modified = FALSE;\r
-\r
-                idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_IMPORT,\r
-                                               CB_GETCURSEL, 0, 0);\r
-                if (idx != CB_ERR && idx != d->lsa_import) {\r
-                    d->lsa_import = idx;\r
-                    d->flags |= K5_CDFLAG_MOD_LSA_IMPORT;\r
-                    modified = TRUE;\r
-                }\r
-\r
-                khui_cfg_set_flags(d->node_main,\r
-                                   (modified)?KHUI_CNFLAG_MODIFIED:0,\r
-                                   KHUI_CNFLAG_MODIFIED);\r
-                return TRUE;\r
-            }\r
-\r
-            if (wParam == MAKEWPARAM(IDC_CFG_INCREALMS, BN_CLICKED)) {\r
-                if (IsDlgButtonChecked(hwnd, IDC_CFG_INCREALMS) ==\r
-                    BST_CHECKED) {\r
-                    d->inc_realms = TRUE;\r
-                } else {\r
-                    d->inc_realms = FALSE;\r
-                }\r
-                d->flags |= K5_CDFLAG_MOD_INC_REALMS;\r
-\r
-                khui_cfg_set_flags(d->node_main,\r
-                                   KHUI_CNFLAG_MODIFIED,\r
-                                   KHUI_CNFLAG_MODIFIED);\r
-                return TRUE;\r
-            }\r
-        }\r
-        break;\r
-\r
-    case KHUI_WM_CFG_NOTIFY:\r
-        {\r
-            k5_config_data * d;\r
-\r
-            d = &k5_config_dlg_data;\r
-\r
-            if (HIWORD(wParam) == WMCFG_APPLY) {\r
-                khm_int32 oflags;\r
-\r
-                oflags = d->flags;\r
-                k5_write_config_data(d);\r
-\r
-                if (d->flags != oflags) {\r
-                    khui_cfg_set_flags(d->node_main,\r
-                                       KHUI_CNFLAG_APPLIED,\r
-                                       KHUI_CNFLAG_APPLIED |\r
-                                       KHUI_CNFLAG_MODIFIED);\r
-                }\r
-                return TRUE;\r
-            }\r
-        }\r
-        break;\r
-\r
-    case WM_DESTROY:\r
-        {\r
-            k5_free_config_data(&k5_config_dlg_data);\r
-            k5_dlg_data_valid = FALSE;\r
-        }\r
-        break;\r
-    }\r
-    return FALSE;\r
-}\r
-\r
-static HIMAGELIST\r
-k5_get_state_image_list(void) {\r
-    HIMAGELIST hil;\r
-    HICON hicon;\r
-\r
-    hil = ImageList_Create(GetSystemMetrics(SM_CXSMICON),\r
-                           GetSystemMetrics(SM_CYSMICON),\r
-                           ILC_COLOR | ILC_MASK,\r
-                           4,\r
-                           2);\r
-\r
-    hicon = LoadImage(hResModule,\r
-                      MAKEINTRESOURCE(IDI_NORMAL),\r
-                      IMAGE_ICON,\r
-                      GetSystemMetrics(SM_CXSMICON),\r
-                      GetSystemMetrics(SM_CYSMICON),\r
-                      LR_DEFAULTCOLOR);\r
-\r
-    ImageList_AddIcon(hil, hicon);\r
-\r
-    DestroyIcon(hicon);\r
-\r
-    hicon = LoadImage(hResModule,\r
-                      MAKEINTRESOURCE(IDI_MODIFIED),\r
-                      IMAGE_ICON,\r
-                      GetSystemMetrics(SM_CXSMICON),\r
-                      GetSystemMetrics(SM_CYSMICON),\r
-                      LR_DEFAULTCOLOR);\r
-\r
-    ImageList_AddIcon(hil, hicon);\r
-\r
-    DestroyIcon(hicon);\r
-\r
-    hicon = LoadImage(hResModule,\r
-                      MAKEINTRESOURCE(IDI_NEW),\r
-                      IMAGE_ICON,\r
-                      GetSystemMetrics(SM_CXSMICON),\r
-                      GetSystemMetrics(SM_CYSMICON),\r
-                      LR_DEFAULTCOLOR);\r
-\r
-    ImageList_AddIcon(hil, hicon);\r
-\r
-    DestroyIcon(hicon);\r
-\r
-    hicon = LoadImage(hResModule,\r
-                      MAKEINTRESOURCE(IDI_DELETED),\r
-                      IMAGE_ICON,\r
-                      GetSystemMetrics(SM_CXSMICON),\r
-                      GetSystemMetrics(SM_CYSMICON),\r
-                      LR_DEFAULTCOLOR);\r
-\r
-    ImageList_AddIcon(hil, hicon);\r
-\r
-    DestroyIcon(hicon);\r
-\r
-    return hil;\r
-}\r
-\r
-static void\r
-k5_update_realms_display(HWND hw_list, k5_config_data * d) {\r
-    khm_size i;\r
-    LVITEM lvi;\r
-    wchar_t buf[64];\r
-\r
-    ListView_DeleteAllItems(hw_list);\r
-\r
-    for (i=0; i < d->n_realms; i++) {\r
-        if ((d->realms[i].flags & K5_RDFLAG_DELETED) &&\r
-            (d->realms[i].flags & K5_RDFLAG_NEW))\r
-            continue;\r
-\r
-        ZeroMemory(&lvi, sizeof(lvi));\r
-        lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;\r
-        lvi.iItem = 0;\r
-        lvi.iSubItem = 0;\r
-        lvi.pszText = d->realms[i].realm;\r
-        lvi.lParam = i;\r
-\r
-        if (d->realms[i].flags & K5_RDFLAG_DELETED) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);\r
-        } else if (d->realms[i].flags & K5_RDFLAG_NEW) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-        } else if (d->realms[i].flags & K5_RDFLAG_MODIFED) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);\r
-        } else {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);\r
-        }\r
-        lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-\r
-        ListView_InsertItem(hw_list, &lvi);\r
-    }\r
-\r
-    ZeroMemory(&lvi, sizeof(lvi));\r
-    lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;\r
-    lvi.iItem = 0;\r
-    lvi.iSubItem = 0;\r
-    lvi.pszText = buf;\r
-    lvi.lParam = (LPARAM) -1;\r
-\r
-    LoadString(hResModule, IDS_CFG_RE_NEWREALM,\r
-               buf, ARRAYLENGTH(buf));\r
-\r
-    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-    lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-\r
-    ListView_InsertItem(hw_list, &lvi);\r
-\r
-    if (d->flags & K5_CDFLAG_MOD_REALMS) {\r
-        khui_cfg_set_flags(d->node_realm, KHUI_CNFLAG_MODIFIED,\r
-                           KHUI_CNFLAG_MODIFIED);\r
-    } else {\r
-        khui_cfg_set_flags(d->node_realm, 0,\r
-                           KHUI_CNFLAG_MODIFIED);\r
-    }\r
-}\r
-\r
-static void\r
-k5_update_kdcs_display(HWND hw_kdc, k5_config_data * d, khm_size idx_rlm) {\r
-    khm_size k;\r
-    LVITEM lvi;\r
-    int idx_item;\r
-    k5_realm_kdc * pkdc;\r
-    wchar_t wyes[8];\r
-    wchar_t wno[8];\r
-    wchar_t wbuf[64];\r
-\r
-    ListView_DeleteAllItems(hw_kdc);\r
-\r
-    if (d == NULL)\r
-        return;\r
-\r
-#ifdef DEBUG\r
-    assert(idx_rlm < d->n_realms);\r
-#endif\r
-    LoadString(hResModule, IDS_YES, wyes, ARRAYLENGTH(wyes));\r
-    LoadString(hResModule, IDS_NO, wno, ARRAYLENGTH(wno));\r
-\r
-    for (k=0; k < d->realms[idx_rlm].n_kdcs; k++) {\r
-        if ((d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_DELETED) &&\r
-            (d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_NEW))\r
-            continue;\r
-\r
-        pkdc = &(d->realms[idx_rlm].kdcs[k]);\r
-\r
-        ZeroMemory(&lvi, sizeof(lvi));\r
-        lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;\r
-        lvi.iItem = K5_MAX_KDC;\r
-        lvi.iSubItem = 0;\r
-        lvi.lParam = k;\r
-        lvi.pszText = pkdc->name;\r
-        if (pkdc->flags & K5_RKFLAG_DELETED) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);\r
-        } else if (pkdc->flags & K5_RKFLAG_NEW) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-        } else if ((pkdc->flags & K5_RKFLAG_MOD_ADMIN) ||\r
-                   (pkdc->flags & K5_RKFLAG_MOD_MASTER)) {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);\r
-        } else {\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);\r
-        }\r
-        lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-\r
-        idx_item = ListView_InsertItem(hw_kdc, &lvi);\r
-\r
-        lvi.mask = LVIF_TEXT;\r
-        lvi.iItem = idx_item;\r
-        lvi.iSubItem = 1;\r
-        if (pkdc->admin)\r
-            lvi.pszText = wyes;\r
-        else\r
-            lvi.pszText = wno;\r
-        ListView_SetItem(hw_kdc, &lvi);\r
-\r
-        lvi.iSubItem = 2;\r
-        if (pkdc->master)\r
-            lvi.pszText = wyes;\r
-        else\r
-            lvi.pszText = wno;\r
-        ListView_SetItem(hw_kdc, &lvi);\r
-    }\r
-\r
-    ZeroMemory(&lvi, sizeof(lvi));\r
-    lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;\r
-    lvi.iItem = 0;\r
-    lvi.iSubItem = 0;\r
-    lvi.pszText = wbuf;\r
-    lvi.lParam = (LPARAM) -1;\r
-    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-    lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-\r
-    LoadString(hResModule, IDS_CFG_RE_NEWSERVER,\r
-               wbuf, ARRAYLENGTH(wbuf));\r
-\r
-    ListView_InsertItem(hw_kdc, &lvi);\r
-}\r
-\r
-static void\r
-k5_update_dmap_display(HWND hw_dm, k5_config_data * d, khm_size idx_rlm) {\r
-    khm_size m;\r
-    LVITEM lvi;\r
-    k5_domain_map * map;\r
-    wchar_t wbuf[64];\r
-\r
-    ListView_DeleteAllItems(hw_dm);\r
-\r
-    if (d == NULL)\r
-        return;\r
-\r
-#ifdef DEBUG\r
-    assert(idx_rlm < d->n_realms);\r
-#endif\r
-\r
-    for (m=0; m < d->realms[idx_rlm].n_domain_maps; m++) {\r
-        map = &(d->realms[idx_rlm].domain_maps[m]);\r
-\r
-        if ((map->flags & K5_DMFLAG_NEW) &&\r
-            (map->flags & K5_DMFLAG_DELETED))\r
-            continue;\r
-\r
-        ZeroMemory(&lvi, sizeof(lvi));\r
-\r
-        lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;\r
-        lvi.pszText = map->name;\r
-        if (map->flags & K5_DMFLAG_DELETED)\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);\r
-        else if (map->flags & K5_DMFLAG_NEW)\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-        else\r
-            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);\r
-        lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-        lvi.lParam = m;\r
-\r
-        lvi.iItem = K5_MAX_DOMAIN_MAPPINGS;\r
-        lvi.iSubItem = 0;\r
-\r
-        ListView_InsertItem(hw_dm, &lvi);\r
-    }\r
-\r
-    ZeroMemory(&lvi, sizeof(lvi));\r
-    lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;\r
-    lvi.pszText = wbuf;\r
-    lvi.lParam = (LPARAM) -1;\r
-    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);\r
-    lvi.stateMask = LVIS_STATEIMAGEMASK;\r
-    lvi.iItem = 0;\r
-    lvi.iSubItem = 0;\r
-\r
-    LoadString(hResModule, IDS_CFG_RE_NEWDMAP,\r
-               wbuf, ARRAYLENGTH(wbuf));\r
-\r
-    ListView_InsertItem(hw_dm, &lvi);\r
-}\r
-\r
-INT_PTR CALLBACK \r
-k5_realms_dlgproc(HWND hwnd,\r
-                  UINT uMsg,\r
-                  WPARAM wParam,\r
-                  LPARAM lParam) {\r
-    k5_config_data * d;\r
-\r
-    d = &k5_config_dlg_data;\r
-\r
-    switch(uMsg) {\r
-    case WM_INITDIALOG:\r
-        {\r
-            LVCOLUMN lvc;\r
-            HWND hw;\r
-            RECT r;\r
-            wchar_t buf[256];\r
-\r
-            assert(k5_dlg_data_valid);\r
-\r
-            d->node_realm = (khui_config_node) lParam;\r
-\r
-            /* set up columns for the Realms list */\r
-            hw = GetDlgItem(hwnd, IDC_CFG_REALMS);\r
-#ifdef DEBUG\r
-            assert(hw);\r
-#endif\r
-            GetWindowRect(hw, &r);\r
-            r.right -= 5;       /* shave a few pixels off the width */\r
-            ZeroMemory(&lvc, sizeof(lvc));\r
-            lvc.mask = LVCF_TEXT | LVCF_WIDTH;\r
-            lvc.pszText = buf;\r
-            lvc.cx = (r.right - r.left);\r
-            LoadString(hResModule, IDS_CFG_RE_REALMS,\r
-                       buf, ARRAYLENGTH(buf));\r
-\r
-            ListView_InsertColumn(hw, 0, &lvc);\r
-\r
-            ListView_SetImageList(hw,\r
-                                  k5_get_state_image_list(),\r
-                                  LVSIL_STATE);\r
-\r
-            k5_update_realms_display(hw, d);\r
-\r
-            /* set up columns for the servers list */\r
-            hw = GetDlgItem(hwnd, IDC_CFG_KDC);\r
-#ifdef DEBUG\r
-            assert(hw);\r
-#endif\r
-            GetWindowRect(hw, &r);\r
-            r.right -= 5;\r
-            ZeroMemory(&lvc, sizeof(lvc));\r
-            lvc.mask = LVCF_TEXT | LVCF_WIDTH;\r
-            lvc.pszText = buf;\r
-            lvc.cx = (r.right - r.left) * 2 / 4;\r
-            LoadString(hResModule, IDS_CFG_RE_HEAD_SVR,\r
-                       buf, ARRAYLENGTH(buf));\r
-\r
-            ListView_InsertColumn(hw, 0, &lvc);\r
-\r
-            lvc.cx = (r.right - r.left) * 1 / 4;\r
-            LoadString(hResModule, IDS_CFG_RE_HEAD_ADMIN,\r
-                       buf, ARRAYLENGTH(buf));\r
-            ListView_InsertColumn(hw, 1, &lvc);\r
-\r
-            LoadString(hResModule, IDS_CFG_RE_HEAD_MASTER,\r
-                       buf, ARRAYLENGTH(buf));\r
-            ListView_InsertColumn(hw, 2, &lvc);\r
-\r
-            ListView_SetImageList(hw,\r
-                                  k5_get_state_image_list(),\r
-                                  LVSIL_STATE);\r
-\r
-            /* set up columns for the domain/host mapping list */\r
-            hw = GetDlgItem(hwnd, IDC_CFG_DMAP);\r
-#ifdef DEBUG\r
-            assert(hw);\r
-#endif\r
-            GetWindowRect(hw, &r);\r
-            r.right -= 5;\r
-            ZeroMemory(&lvc, sizeof(lvc));\r
-            lvc.mask = LVCF_TEXT | LVCF_WIDTH;\r
-            lvc.pszText = buf;\r
-            lvc.cx = (r.right - r.left);\r
-            LoadString(hResModule, IDS_CFG_RE_HEAD_DOMAIN,\r
-                       buf, ARRAYLENGTH(buf));\r
-\r
-            ListView_InsertColumn(hw, 0, &lvc);\r
-\r
-\r
-            ListView_SetImageList(hw,\r
-                                  k5_get_state_image_list(),\r
-                                  LVSIL_STATE);\r
-        }\r
-        break;\r
-\r
-    case WM_NOTIFY:\r
-        {\r
-            LPNMHDR pnmh;\r
-            HWND hw_rlm = NULL;\r
-            HWND hw_kdc = NULL;\r
-            HWND hw_dmp = NULL;\r
-            int i;\r
-\r
-            pnmh = (LPNMHDR) lParam;\r
-\r
-            if (pnmh->idFrom == IDC_CFG_REALMS) {\r
-\r
-                hw_rlm = pnmh->hwndFrom;\r
-\r
-                switch(pnmh->code) {\r
-                case LVN_ITEMCHANGED:\r
-                    i = ListView_GetSelectedCount(hw_rlm);\r
-                    hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);\r
-                    hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);\r
-\r
-                    d->c_realm = (khm_size) -1;\r
-                    \r
-                    if (i == 1) {\r
-                        LVITEM lvi;\r
-\r
-                        i = ListView_GetNextItem(hw_rlm, -1,\r
-                                                 LVNI_SELECTED);\r
-                        if (i == -1)\r
-                            goto _no_selection;\r
-\r
-                        ZeroMemory(&lvi, sizeof(lvi));\r
-\r
-                        lvi.iItem = i;\r
-                        lvi.iSubItem = 0;\r
-                        lvi.mask = LVIF_PARAM;\r
-\r
-                        ListView_GetItem(hw_rlm, &lvi);\r
-\r
-                        if (lvi.lParam == -1)\r
-                            goto _no_selection;\r
-\r
-                        d->c_realm = lvi.lParam;\r
-\r
-                        k5_update_kdcs_display(hw_kdc, d, lvi.lParam);\r
-                        k5_update_dmap_display(hw_dmp, d, lvi.lParam);\r
-                        return TRUE;\r
-                    }\r
-\r
-                _no_selection:\r
-                    ListView_DeleteAllItems(hw_kdc);\r
-                    ListView_DeleteAllItems(hw_dmp);\r
-                    break;\r
-\r
-                case LVN_BEGINLABELEDIT:\r
-                    {\r
-                        NMLVDISPINFO * pdisp;\r
-                        LVITEM lvi;\r
-\r
-                        pdisp = (NMLVDISPINFO *) lParam;\r
-\r
-                        ZeroMemory(&lvi, sizeof(lvi));\r
-                        lvi.iItem = pdisp->item.iItem;\r
-                        lvi.mask = LVIF_PARAM;\r
-\r
-                        ListView_GetItem(hw_rlm, &lvi);\r
-\r
-                        if (pdisp->item.iItem == -1 ||\r
-                            lvi.lParam != -1) {\r
-                            SetWindowLongPtr(hwnd, DWL_MSGRESULT, TRUE);\r
-                        } else {\r
-                            /* allow editing */\r
-                            HWND hw_edit;\r
-\r
-                            hw_edit = ListView_GetEditControl(hw_rlm);\r
-                            if (hw_edit != NULL) {\r
-                                SendMessage(hw_edit,\r
-                                            EM_SETLIMITTEXT,\r
-                                            K5_MAXCCH_REALM - 1,\r
-                                            0);\r
-                            }\r
-                            SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);\r
-                        }\r
-\r
-                        return TRUE;\r
-                    }\r
-                    break;\r
-\r
-                case LVN_ENDLABELEDIT:\r
-                    {\r
-                        NMLVDISPINFO * pdisp;\r
-                        khm_size n;\r
-\r
-                        pdisp = (NMLVDISPINFO *) lParam;\r
-\r
-                        if (pdisp->item.pszText) {\r
-                            n = d->n_realms;\r
-                            k5_assert_n_realms(d, n+1);\r
-                            StringCbCopy(d->realms[n].realm,\r
-                                         sizeof(d->realms[n].realm),\r
-                                         pdisp->item.pszText);\r
-                            d->realms[n].flags = K5_RDFLAG_NEW;\r
-                            d->n_realms++;\r
-\r
-                            d->flags |= K5_CDFLAG_MOD_REALMS;\r
-\r
-                            k5_update_realms_display(hw_rlm, d);\r
-                        }\r
-\r
-                        return TRUE;\r
-                    }\r
-                    break;\r
-\r
-                case LVN_KEYDOWN:\r
-                    {\r
-                        NMLVKEYDOWN * pnmk;\r
-                        LVITEM lvi;\r
-                        khm_size r;\r
-                        int idx;\r
-                        BOOL modified = FALSE;\r
-\r
-                        pnmk = (NMLVKEYDOWN *) lParam;\r
-\r
-                        if (pnmk->wVKey == VK_DELETE) {\r
-                            idx = -1;\r
-                            while((idx = ListView_GetNextItem(hw_rlm, idx,\r
-                                                              LVNI_SELECTED))\r
-                                  != -1) {\r
-                                ZeroMemory(&lvi, sizeof(lvi));\r
-                                lvi.iItem = idx;\r
-                                lvi.iSubItem = 0;\r
-                                lvi.mask = LVIF_PARAM;\r
-\r
-                                ListView_GetItem(hw_rlm, &lvi);\r
-\r
-                                if (lvi.lParam != -1 &&\r
-                                    (r = lvi.lParam) < d->n_realms) {\r
-                                    d->realms[r].flags ^= K5_RDFLAG_DELETED;\r
-                                    modified = TRUE;\r
-                                }\r
-                            }\r
-\r
-                            if (modified) {\r
-                                d->flags |= K5_CDFLAG_MOD_REALMS;\r
-\r
-                                k5_purge_config_data(d, TRUE, TRUE, TRUE);\r
-                                k5_update_realms_display(hw_rlm, d);\r
-                                k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);\r
-                                k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);\r
-                            }\r
-                            return TRUE;\r
-                        }\r
-                    }\r
-                    break;\r
-                }\r
-            } else if (pnmh->idFrom == IDC_CFG_KDC) {\r
-                hw_kdc = pnmh->hwndFrom;\r
-\r
-                switch (pnmh->code) {\r
-                case LVN_BEGINLABELEDIT:\r
-                    {\r
-                        NMLVDISPINFO * pdisp;\r
-                        LVITEM lvi;\r
-\r
-                        pdisp = (NMLVDISPINFO *) lParam;\r
-\r
-                        ZeroMemory(&lvi, sizeof(lvi));\r
-                        lvi.iItem = pdisp->item.iItem;\r
-                        lvi.mask = LVIF_PARAM;\r
-\r
-                        ListView_GetItem(hw_kdc, &lvi);\r
-\r
-                        if (pdisp->item.iItem == -1 ||\r
-                            lvi.lParam != -1) {\r
-                            SetWindowLongPtr(hwnd, DWL_MSGRESULT, TRUE);\r
-                        } else {\r
-                            /* allow editing */\r
-                            HWND hw_edit;\r
-\r
-                            hw_edit = ListView_GetEditControl(hw_kdc);\r
-                            if (hw_edit != NULL) {\r
-                                SendMessage(hw_edit,\r
-                                            EM_SETLIMITTEXT,\r
-                                            K5_MAXCCH_HOST - 1,\r
-                                            0);\r
-                            }\r
-                            SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);\r
-                        }\r
-                        return TRUE;\r
-                    }\r
-                    break;\r
-\r
-                case LVN_ENDLABELEDIT:\r
-                    {\r
-                        NMLVDISPINFO * pdisp;\r
-                        khm_size r;\r
-                        khm_size k;\r
-\r
-                        r = d->c_realm;\r
-\r
-                        pdisp = (NMLVDISPINFO *) lParam;\r
-\r
-                        if (pdisp->item.pszText) {\r
-                            k = d->realms[r].n_kdcs;\r
-\r
-                            if (k >= K5_MAX_KDC) {\r
-                                SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);\r
-                                /* TODO: show a message box saying\r
-                                   there are too many KDC's\r
-                                   already. */\r
-                                return TRUE;\r
-                            }\r
-\r
-                            StringCbCopy(d->realms[r].kdcs[k].name,\r
-                                         sizeof(d->realms[0].kdcs[0].name),\r
-                                         pdisp->item.pszText);\r
-                            d->realms[r].kdcs[k].flags = K5_RKFLAG_NEW;\r
-                            d->realms[r].n_kdcs++;\r
-\r
-                            d->realms[r].flags |= K5_RDFLAG_MODIFED;\r
-\r
-                            k5_update_kdcs_display(hw_kdc, d, d->c_realm);\r
-                        }\r
-                        return TRUE;\r
-                    }\r
-                    break;\r
-\r
-                case LVN_KEYDOWN:\r
-                    {\r
-#if 0\r
-                        NMLVKEYDOWN * pnmk;\r
-                        LVITEM lvi;\r
-                        khm_size r;\r
-                        int idx;\r
-                        BOOL modified = FALSE;\r
-\r
-                        pnmk = (NMLVKEYDOWN *) lParam;\r
-\r
-                        if (pnmk->wVKey == VK_DELETE) {\r
-                            idx = -1;\r
-                            while((idx = ListView_GetNextItem(hw_rlm, idx,\r
-                                                              LVNI_SELECTED))\r
-                                  != -1) {\r
-                                ZeroMemory(&lvi, sizeof(lvi));\r
-                                lvi.iItem = idx;\r
-                                lvi.iSubItem = 0;\r
-                                lvi.mask = LVIF_PARAM;\r
-\r
-                                ListView_GetItem(hw_rlm, &lvi);\r
-\r
-                                if (lvi.lParam != -1 &&\r
-                                    (r = lvi.lParam) < d->n_realms) {\r
-                                    d->realms[r].flags ^= K5_RDFLAG_DELETED;\r
-                                    modified = TRUE;\r
-                                }\r
-                            }\r
-\r
-                            if (modified) {\r
-                                d->flags |= K5_CDFLAG_MOD_REALMS;\r
-\r
-                                k5_purge_config_data(d, TRUE, TRUE, TRUE);\r
-                                k5_update_realms_display(hw_rlm, d);\r
-                                k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);\r
-                                k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);\r
-                            }\r
-                            return TRUE;\r
-                        }\r
-#endif\r
-                    }\r
-                    break;\r
-                }\r
-            }\r
-        }\r
-        break;\r
-\r
-    case WM_DESTROY:\r
-        break;\r
-    }\r
-    return FALSE;\r
-}\r
-\r
-void\r
-k5_register_config_panels(void) {\r
-    khui_config_node node;\r
-    khui_config_node_reg reg;\r
-    wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];\r
-    wchar_t wlong[KHUI_MAXCCH_LONG_DESC];\r
-\r
-    ZeroMemory(&reg, sizeof(reg));\r
-\r
-    LoadString(hResModule, IDS_K5CFG_SHORT_DESC,\r
-               wshort, ARRAYLENGTH(wshort));\r
-    LoadString(hResModule, IDS_K5CFG_LONG_DESC,\r
-               wlong, ARRAYLENGTH(wlong));\r
-\r
-    reg.name = L"Kerberos5";\r
-    reg.short_desc = wshort;\r
-    reg.long_desc = wlong;\r
-    reg.h_module = hResModule;\r
-    reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);\r
-    reg.dlg_proc = k5_config_dlgproc;\r
-    reg.flags = 0;\r
-\r
-    khui_cfg_register(NULL, &reg);\r
-\r
-    if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {\r
-        node = NULL;\r
-#ifdef DEBUG\r
-        assert(FALSE);\r
-#endif\r
-    }\r
-\r
-#ifdef REALM_EDITOR\r
-    ZeroMemory(&reg, sizeof(reg));\r
-\r
-    LoadString(hResModule, IDS_K5RLM_SHORT_DESC,\r
-               wshort, ARRAYLENGTH(wshort));\r
-    LoadString(hResModule, IDS_K5RLM_LONG_DESC,\r
-               wlong, ARRAYLENGTH(wlong));\r
-\r
-    reg.name = L"KerberosRealms";\r
-    reg.short_desc = wshort;\r
-    reg.long_desc = wlong;\r
-    reg.h_module = hResModule;\r
-    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS);\r
-    reg.dlg_proc = k5_realms_dlgproc;\r
-    reg.flags = 0;\r
-\r
-    khui_cfg_register(node, &reg);\r
-#endif\r
-\r
-    ZeroMemory(&reg, sizeof(reg));\r
-\r
-    LoadString(hResModule, IDS_K5CCC_SHORT_DESC,\r
-               wshort, ARRAYLENGTH(wshort));\r
-    LoadString(hResModule, IDS_K5CCC_LONG_DESC,\r
-               wlong, ARRAYLENGTH(wlong));\r
-\r
-    reg.name = L"KerberosCCaches";\r
-    reg.short_desc = wshort;\r
-    reg.long_desc = wlong;\r
-    reg.h_module = hResModule;\r
-    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_CACHES);\r
-    reg.dlg_proc = k5_ccconfig_dlgproc;\r
-    reg.flags = 0;\r
-\r
-    khui_cfg_register(node, &reg);\r
-\r
-    khui_cfg_release(node);\r
-\r
-    if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {\r
-        node = NULL;\r
-#ifdef DEBUG\r
-        assert(FALSE);\r
-#endif\r
-    }\r
-\r
-    ZeroMemory(&reg, sizeof(reg));\r
-\r
-    LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC,\r
-               wshort, ARRAYLENGTH(wshort));\r
-    LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC,\r
-               wlong, ARRAYLENGTH(wlong));\r
-\r
-    reg.name = L"KerberosIdentities";\r
-    reg.short_desc = wshort;\r
-    reg.long_desc = wlong;\r
-    reg.h_module = hResModule;\r
-    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);\r
-    reg.dlg_proc = k5_ids_tab_dlgproc;\r
-    reg.flags = KHUI_CNFLAG_SUBPANEL;\r
-\r
-    khui_cfg_register(node, &reg);\r
-\r
-    ZeroMemory(&reg, sizeof(reg));\r
-\r
-    LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC,\r
-               wshort, ARRAYLENGTH(wshort));\r
-    LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC,\r
-               wlong, ARRAYLENGTH(wlong));\r
-\r
-    reg.name = L"KerberosIdentitiesPlural";\r
-    reg.short_desc = wshort;\r
-    reg.long_desc = wlong;\r
-    reg.h_module = hResModule;\r
-    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);\r
-    reg.dlg_proc = k5_id_tab_dlgproc;\r
-    reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;\r
-\r
-    khui_cfg_register(node, &reg);\r
-\r
-    khui_cfg_release(node);\r
-}\r
-\r
-void\r
-k5_unregister_config_panels(void) {\r
-    khui_config_node node_main;\r
-#ifdef REALM_EDITOR\r
-    khui_config_node node_realms;\r
-#endif\r
-    khui_config_node node_ids;\r
-    khui_config_node node_tab;\r
-    khui_config_node node_ccaches;\r
-\r
-    if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) {\r
-        node_main = NULL;\r
-#ifdef DEBUG\r
-        assert(FALSE);\r
-#endif\r
-    }\r
-\r
-#ifdef REALM_EDITOR\r
-    if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms", \r
-                                    &node_realms))) {\r
-        khui_cfg_remove(node_realms);\r
-        khui_cfg_release(node_realms);\r
-    }\r
-#ifdef DEBUG\r
-    else\r
-        assert(FALSE);\r
-#endif\r
-#endif\r
-\r
-    if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosCCaches",\r
-                                    &node_ccaches))) {\r
-        khui_cfg_remove(node_ccaches);\r
-        khui_cfg_release(node_ccaches);\r
-    }\r
-#ifdef DEBUG\r
-    else\r
-        assert(FALSE);\r
-#endif\r
-\r
-    if (node_main) {\r
-        khui_cfg_remove(node_main);\r
-        khui_cfg_release(node_main);\r
-    }\r
-\r
-    if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) {\r
-        node_ids = NULL;\r
-#ifdef DEBUG\r
-        assert(FALSE);\r
-#endif\r
-    }\r
-\r
-    if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) {\r
-        khui_cfg_remove(node_tab);\r
-        khui_cfg_release(node_tab);\r
-    }\r
-    if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) {\r
-        khui_cfg_remove(node_tab);\r
-        khui_cfg_release(node_tab);\r
-    }\r
-\r
-    if (node_ids)\r
-        khui_cfg_release(node_ids);\r
-}\r
+/*
+ * Copyright (c) 2005 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<assert.h>
+#include<lm.h>
+#include<commctrl.h>
+
+#pragma warning(push)
+#pragma warning(disable: 4995)
+#include<shlwapi.h>
+#pragma warning(pop)
+
+
+typedef struct tag_k5_realm_kdc {
+    wchar_t       name[K5_MAXCCH_HOST];
+    khm_boolean   admin;        /* admin server? */
+    khm_boolean   master;       /* master kdc? */
+    khm_int32     flags;
+} k5_realm_kdc;
+
+#define K5_RKFLAG_DELETED    1
+#define K5_RKFLAG_NEW        2
+#define K5_RKFLAG_MOD_ADMIN  4
+#define K5_RKFLAG_MOD_MASTER 8
+
+typedef struct tag_k5_domain_map {
+    wchar_t       name[K5_MAXCCH_HOST]; /* name of host that maps to a
+                                           realm */
+    khm_int32     flags;
+} k5_domain_map;
+
+#define K5_DMFLAG_DELETED 1
+#define K5_DMFLAG_NEW     2
+
+typedef struct tag_k5_realm_data {
+    wchar_t       realm[K5_MAXCCH_REALM];
+    k5_realm_kdc  kdcs[K5_MAX_KDC];
+    khm_size      n_kdcs;
+    k5_domain_map domain_maps[K5_MAX_DOMAIN_MAPPINGS];
+    khm_size      n_domain_maps;
+
+    khm_int32     flags;
+} k5_realm_data;
+
+#define K5_RDFLAG_DELETED 1
+#define K5_RDFLAG_NEW     2
+#define K5_RDFLAG_MODIFED 4
+
+#define K5_REALMS_ALLOC_INCR 8
+
+typedef struct tag_k5_config_data {
+    wchar_t       def_realm[K5_MAXCCH_REALM];    /* default realm */
+
+    wchar_t       config_file[MAX_PATH]; /* path to configuration file */
+    khm_boolean   create_config_file; /* create config_file if missing? */
+    khm_boolean   inc_realms;   /* include full realm list in new
+                                   credentials dialog? */
+
+    /* [libdefaults] */
+    khm_boolean   dns_lookup_kdc;
+    khm_boolean   dns_lookup_realm;
+    khm_boolean   dns_fallback;
+
+    khm_boolean   noaddresses;
+
+    k5_lsa_import lsa_import;   /* import mslsa creds? */
+
+    /* [realms] */
+    k5_realm_data *realms;
+    khm_size      n_realms;
+    khm_size      nc_realms;
+    khm_size      c_realm;
+
+    khui_config_node node_main;
+    khui_config_node node_realm;
+
+    khm_int32     flags;
+
+    /* used by the realm editor */
+    HMENU         hm_realms_ctx;
+    HMENU         hm_kdc_ctx;
+    HMENU         hm_dmap_ctx;
+} k5_config_data;
+
+#define K5_CDFLAG_MOD_DEF_REALM      0x00000001
+#define K5_CDFLAG_MOD_CONF_FILE      0x00000002
+#define K5_CDFLAG_MOD_DNS_LOOKUP_KDC 0x00000004
+#define K5_CDFLAG_MOD_DNS_LOOKUP_RLM 0x00000008
+#define K5_CDFLAG_MOD_DNS_FALLBACK   0x00000010
+#define K5_CDFLAG_MOD_NOADDRESSES    0x00000020
+#define K5_CDFLAG_MOD_LSA_IMPORT     0x00000040
+#define K5_CDFLAG_MOD_CREATE_CONF    0x00000080
+#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));
+}
+
+void
+k5_free_config_data(k5_config_data * d) {
+    if (d->realms)
+        PFREE(d->realms);
+
+    k5_init_config_data(d);
+}
+
+static void
+k5_assert_n_realms(k5_config_data * d, khm_size n) {
+    khm_size nc_realms;
+
+    if (n <= d->nc_realms)
+        return;
+
+    nc_realms = UBOUNDSS(n, K5_REALMS_ALLOC_INCR, K5_REALMS_ALLOC_INCR);
+    assert(nc_realms > d->nc_realms);
+
+    d->realms = PREALLOC(d->realms, nc_realms * sizeof(*(d->realms)));
+    d->nc_realms = nc_realms;
+
+    ZeroMemory(&d->realms[d->n_realms],
+               (d->nc_realms - d->n_realms) * sizeof(*(d->realms)));
+}
+
+void
+k5_purge_config_data(k5_config_data * d,
+                     khm_boolean purge_realms,
+                     khm_boolean purge_kdcs,
+                     khm_boolean purge_dmap) {
+    khm_size r;
+    khm_size k;
+    khm_size m;
+
+    for (r=0; r < d->n_realms; r++) {
+        if (purge_realms &&
+            (d->realms[r].flags & K5_RDFLAG_NEW) &&
+            (d->realms[r].flags & K5_RDFLAG_DELETED)) {
+
+            if (d->n_realms > r+1)
+                MoveMemory(&d->realms[r], &d->realms[r+1],
+                           sizeof(d->realms[0]) * (d->n_realms - (r+1)));
+            r--;
+            d->n_realms--;
+            continue;
+        }
+
+        for (k=0; k < d->realms[r].n_kdcs; k++) {
+            if (purge_kdcs &&
+                (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+                (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
+                if (d->realms[r].n_kdcs > k + 1)
+                    MoveMemory(&d->realms[r].kdcs[k],
+                               &d->realms[r].kdcs[k+1],
+                               sizeof(d->realms[0].kdcs[0]) *
+                               (d->realms[r].n_kdcs - (k+1)));
+                k--;
+                d->realms[r].n_kdcs--;
+                continue;
+            }
+        }
+
+        if (K5_MAX_KDC > k+1)
+            ZeroMemory(&d->realms[r].kdcs[k],
+                       sizeof(d->realms[0].kdcs[0]) *
+                       (K5_MAX_KDC - (k + 1)));
+
+        for (m=0; m < d->realms[r].n_domain_maps; m++) {
+            if (purge_dmap &&
+                (d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&
+                (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) {
+                if (d->realms[r].n_domain_maps > m + 1)
+                    MoveMemory(&d->realms[r].domain_maps[m],
+                               &d->realms[r].domain_maps[m+1],
+                               sizeof(d->realms[0].domain_maps[0]) *
+                               (d->realms[r].n_domain_maps - (m+1)));
+                m--;
+                d->realms[r].n_domain_maps--;
+                continue;
+            }
+        }
+
+        if (K5_MAX_DOMAIN_MAPPINGS > m+1)
+            ZeroMemory(&d->realms[r].domain_maps[m],
+                       sizeof(d->realms[0].domain_maps[0]) *
+                       (K5_MAX_DOMAIN_MAPPINGS - (m+1)));
+    }
+
+    if (d->nc_realms > r + 1)
+        ZeroMemory(&d->realms[r],
+                   sizeof(d->realms[0]) *
+                   (d->nc_realms - (r + 1)));
+}
+
+static khm_boolean
+k5_is_profile_loaded(void) {
+#ifdef DEBUG
+    assert(pprofile_init);
+    assert(pprofile_get_subsection_names);
+    assert(pprofile_get_values);
+    assert(pprofile_get_string);
+    assert(pprofile_get_relation_names);
+    assert(pprofile_free_list);
+    assert(pprofile_release_string);
+    assert(pprofile_release);
+    assert(pprofile_clear_relation);
+    assert(pprofile_add_relation);
+    assert(pprofile_update_relation);
+    assert(pprofile_flush);
+#endif
+
+    if (!pprofile_init ||
+        !pprofile_get_subsection_names ||
+        !pprofile_get_values ||
+        !pprofile_get_string ||
+        !pprofile_get_relation_names ||
+        !pprofile_free_list ||
+        !pprofile_release_string ||
+        !pprofile_release ||
+        !pprofile_clear_relation ||
+        !pprofile_add_relation ||
+        !pprofile_update_relation ||
+        !pprofile_flush)
+
+        return FALSE;
+
+    return TRUE;
+}
+
+void
+k5_read_config_data(k5_config_data * d) {
+    wchar_t * defrealm;
+    char config_file[MAX_PATH];
+    profile_t profile = NULL;
+    const char *filenames[2];
+    long rv;
+    khm_size s;
+
+    if (!k5_is_profile_loaded())
+        return;
+
+    defrealm = khm_krb5_get_default_realm();
+
+    if (defrealm) {
+        StringCbCopy(d->def_realm, sizeof(d->def_realm), defrealm);
+        PFREE(defrealm);
+    } else {
+        StringCbCopy(d->def_realm, sizeof(d->def_realm), L"");
+    }
+
+    khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
+
+    AnsiStrToUnicode(d->config_file, sizeof(d->config_file), config_file);
+
+    filenames[0] = config_file;
+    filenames[1] = NULL;
+
+    rv = pprofile_init(filenames, &profile);
+
+    if (!rv) {
+        const char * sec_realms[] = { "realms", NULL };
+        const char * sec_domain_realm[] = { "domain_realm", NULL };
+        char ** sections;
+        char ** dr_from;
+        char * boolv;
+
+        /* first fish out a few values from [libdefaults] */
+
+        rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc",
+                                 NULL, NULL, &boolv);
+        if (!rv && boolv) {
+            d->dns_lookup_kdc = k5_parse_boolean(boolv);
+            pprofile_release_string(boolv);
+        } else
+            d->dns_lookup_kdc = FALSE;
+
+        rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm",
+                                 NULL, NULL, &boolv);
+        if (!rv && boolv) {
+            d->dns_lookup_realm = k5_parse_boolean(boolv);
+            pprofile_release_string(boolv);
+        } else
+            d->dns_lookup_realm = FALSE;
+
+        rv = pprofile_get_string(profile, "libdefaults", "dns_fallback",
+                                 NULL, NULL, &boolv);
+        if (!rv && boolv) {
+            d->dns_fallback = k5_parse_boolean(boolv);
+            pprofile_release_string(boolv);
+        } else
+            d->dns_fallback = FALSE;
+
+        rv = pprofile_get_string(profile, "libdefaults", "noaddresses",
+                                 NULL, NULL, &boolv);
+        if (!rv && boolv) {
+            d->noaddresses = k5_parse_boolean(boolv);
+            pprofile_release_string(boolv);
+        } else
+            d->noaddresses = TRUE;
+
+        /* now we look at the [realms] section */
+        rv = pprofile_get_subsection_names(profile, sec_realms, &sections);
+
+        /* what? no realms? whatever */
+        if (rv) goto _skip_realms;
+
+        /* get a count first */
+        for (s=0; sections[s] && sections[s][0]; s++);
+
+        k5_assert_n_realms(d, s);
+        d->n_realms = s;
+
+        /* now go through each and fish out the kdcs, admin_server
+           and master_kdc. */
+        for (s=0; sections[s] && sections[s][0]; s++) {
+            const char * sec_kdcs[] = 
+                { "realms", sections[s], "kdc", NULL };
+
+            const char * sec_admin[] =
+                { "realms", sections[s], "admin_server", NULL };
+
+            const char * sec_master[] =
+                { "realms", sections[s], "master_kdc", NULL };
+
+            char ** values;
+
+            AnsiStrToUnicode(d->realms[s].realm, sizeof(d->realms[s].realm),
+                             sections[s]);
+            d->realms[s].n_kdcs = 0;
+            d->realms[s].n_domain_maps = 0;
+
+            rv = pprofile_get_values(profile, sec_kdcs, &values);
+            if (!rv) {
+                khm_size i;
+
+                for (i=0 ; values[i] && values[i][0] && i < K5_MAX_KDC; i++) {
+                    AnsiStrToUnicode(d->realms[s].kdcs[i].name,
+                                     sizeof(d->realms[s].kdcs[i].name),
+                                     values[i]);
+
+                }
+                d->realms[s].n_kdcs = i;
+
+                pprofile_free_list(values);
+            }
+
+            rv = pprofile_get_values(profile, sec_admin, &values);
+            if (!rv) {
+                khm_size i;
+                khm_size j;
+                wchar_t kdc_name[K5_MAXCCH_HOST];
+
+                for (i=0; values[i] && values[i][0]; i++) {
+                    AnsiStrToUnicode(kdc_name,
+                                     sizeof(kdc_name), values[i]);
+
+                    for (j=0; j < d->realms[s].n_kdcs; j++)
+                        if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
+                            break;
+
+                    if (j < d->realms[s].n_kdcs) {
+                        d->realms[s].kdcs[j].admin = TRUE;
+                    } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
+                        j = d->realms[s].n_kdcs;
+                        StringCbCopy(d->realms[s].kdcs[j].name,
+                                     sizeof(d->realms[s].kdcs[j].name),
+                                     kdc_name);
+                        d->realms[s].kdcs[j].admin = TRUE;
+                        d->realms[s].n_kdcs ++;
+                    }
+                }
+                pprofile_free_list(values);
+            }
+
+            rv = pprofile_get_values(profile, sec_master, &values);
+            if (!rv) {
+                khm_size i;
+                khm_size j;
+                wchar_t kdc_name[K5_MAXCCH_HOST];
+
+                for (i=0; values[i] && values[i][0]; i++) {
+                    AnsiStrToUnicode(kdc_name, sizeof(kdc_name), values[i]);
+
+                    for (j=0; j < d->realms[s].n_kdcs; j++)
+                        if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
+                            break;
+
+                    if (j < d->realms[s].n_kdcs) {
+                        d->realms[s].kdcs[j].master = TRUE;
+                    } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
+                        j = d->realms[s].n_kdcs;
+                        StringCbCopy(d->realms[s].kdcs[j].name,
+                                     sizeof(d->realms[s].kdcs[j].name),
+                                     kdc_name);
+                        d->realms[s].kdcs[j].master = TRUE;
+                        d->realms[s].n_kdcs ++;
+                    }
+                }
+
+                pprofile_free_list(values);
+            }
+        }
+        pprofile_free_list(sections);
+
+    _skip_realms:
+
+        rv = pprofile_get_relation_names(profile, sec_domain_realm, &dr_from);
+        if (!rv) {
+            khm_size i;
+            khm_size j;
+            char * dr_to;
+            wchar_t wdr_from[K5_MAXCCH_HOST];
+            wchar_t wdr_to[K5_MAXCCH_HOST];
+
+            for (i=0; dr_from[i] && dr_from[i][0]; i++) {
+                AnsiStrToUnicode(wdr_from, sizeof(wdr_from), dr_from[i]);
+
+                rv = pprofile_get_string(profile, "domain_realm", dr_from[i],
+                                         NULL, NULL, &dr_to);
+
+                if (rv || !dr_to)
+                    continue;
+
+                AnsiStrToUnicode(wdr_to, sizeof(wdr_to), dr_to);
+
+                for (j=0; j < d->n_realms; j++) {
+                    if (!wcsicmp(wdr_to, d->realms[j].realm))
+                        break;
+                }
+
+                if (j >= d->n_realms) {
+                    j = d->n_realms;
+                    k5_assert_n_realms(d, j + 1);
+
+                    StringCbCopy(d->realms[j].realm,
+                                 sizeof(d->realms[j].realm),
+                                 wdr_to);
+                    d->realms[j].n_kdcs = 0;
+                    d->realms[j].n_domain_maps = 0;
+
+                    d->n_realms++;
+                }
+
+                if (d->realms[j].n_domain_maps < K5_MAX_DOMAIN_MAPPINGS) {
+                    khm_size k;
+
+                    k = d->realms[j].n_domain_maps;
+
+                    StringCbCopy(d->realms[j].domain_maps[k].name,
+                                 sizeof(d->realms[j].domain_maps[k].name),
+                                 wdr_from);
+
+                    d->realms[j].n_domain_maps++;
+                }
+
+                pprofile_release_string(dr_to);
+            }
+            pprofile_free_list(dr_from);
+        }
+        pprofile_release(profile);
+    }
+
+    {
+        khm_int32 t;
+
+        /* last, read the MSLSA import setting */
+        if (KHM_SUCCEEDED(khc_read_int32(csp_params,
+                                         L"MsLsaImport", &t))) {
+            d->lsa_import = t;
+        } else {
+            d->lsa_import = K5_LSAIMPORT_ALWAYS;
+        }
+
+        if (KHM_SUCCEEDED(khc_read_int32(csp_params,
+                                         L"UseFullRealmList", &t))) {
+            d->inc_realms = !!t;
+        } else {
+            d->inc_realms = TRUE;
+        }
+    }
+
+    d->flags = 0;
+}
+
+void
+k5_write_config_data(k5_config_data * d) {
+    char astr[MAX_PATH * 2];
+    char config_file[MAX_PATH];
+    profile_t profile = NULL;
+    const char *filenames[2];
+    long rv;
+    khm_size s;
+
+    if (d->flags == 0)
+        return;
+
+    if (!k5_is_profile_loaded())
+        return;
+
+    if (d->flags & K5_CDFLAG_MOD_DEF_REALM) {
+        if (SUCCEEDED(StringCbLength(d->def_realm,
+                                     sizeof(d->def_realm), &s)) &&
+            s > 0) {
+            khm_krb5_set_default_realm(d->def_realm);
+        }
+        d->flags &= ~K5_CDFLAG_MOD_DEF_REALM;
+    }
+
+    /* 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;
+    }
+
+    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;
+    }
+
+    if (!(d->flags & 
+          (K5_CDFLAG_MOD_CONF_FILE |
+           K5_CDFLAG_MOD_DNS_FALLBACK |
+           K5_CDFLAG_MOD_DNS_LOOKUP_RLM |
+           K5_CDFLAG_MOD_DNS_LOOKUP_KDC |
+           K5_CDFLAG_MOD_NOADDRESSES |
+           K5_CDFLAG_MOD_CREATE_CONF |
+           K5_CDFLAG_MOD_REALMS))) {
+
+        d->flags = 0;
+        return;
+    }
+
+    khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
+
+    UnicodeStrToAnsi(astr, sizeof(astr), d->config_file);
+
+    if (stricmp(config_file, astr)) {
+        assert(FALSE);
+    }
+
+    filenames[0] = config_file;
+    filenames[1] = NULL;
+
+    rv = pprofile_init(filenames, &profile);
+
+#if FAILOVER_TO_TEMPORARY_FILE
+    if (rv) {
+        char temp_file[MAX_PATH];
+
+        khm_krb5_get_temp_profile_file(temp_file,
+                                       ARRAYLENGTH(temp_file));
+
+        filenames[0] = temp_file;
+
+        rv = pprofile_init(filenames, &profile);
+
+            ?? TODO: Also warn if we are doing this
+    }
+#endif
+
+    if (!rv) {
+        const char * sec_realms[] = { "realms", NULL };
+        const char * sec_domain_realm[] = { "domain_realm", NULL };
+        const char * sec_libdefaults[] = { "libdefaults", NULL, NULL };
+        khm_size r;
+
+        if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_KDC) {
+
+            sec_libdefaults[1] = "dns_lookup_kdc";
+
+            pprofile_clear_relation(profile, sec_libdefaults);
+
+            rv = pprofile_add_relation(profile, sec_libdefaults,
+                                       (d->dns_lookup_kdc)?
+                                       conf_yes[0]:
+                                       conf_no[0]);
+            d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC;
+        }
+
+
+        if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
+
+            sec_libdefaults[1] = "dns_lookup_realm";
+
+            pprofile_clear_relation(profile, sec_libdefaults);
+
+            rv = pprofile_add_relation(profile, sec_libdefaults,
+                                       (d->dns_lookup_realm)?
+                                       conf_yes[0]:
+                                       conf_no[0]);
+
+            d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM;
+        }
+
+        if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
+
+            sec_libdefaults[1] = "dns_fallback";
+
+            pprofile_clear_relation(profile, sec_libdefaults);
+
+            rv = pprofile_add_relation(profile, sec_libdefaults,
+                                       (d->dns_fallback)?
+                                       conf_yes[0]:
+                                       conf_no[0]);
+
+            d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK;
+        }
+
+        if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
+
+            sec_libdefaults[1] = "noaddresses";
+
+            pprofile_clear_relation(profile, sec_libdefaults);
+
+            rv = pprofile_add_relation(profile, sec_libdefaults,
+                                       (d->noaddresses)?
+                                       conf_yes[0]:
+                                       conf_no[0]);
+
+            d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES;
+        }
+
+        /* now we look at the [realms] section */
+
+        for (r=0; r < d->n_realms; r++) {
+            char realm[K5_MAXCCH_REALM];
+            char host[K5_MAXCCH_HOST];
+
+            const char * sec_kdcs[] = 
+                { "realms", realm, "kdc", NULL };
+
+            const char * sec_admin[] =
+                { "realms", realm, "admin_server", NULL };
+
+            const char * sec_master[] =
+                { "realms", realm, "master_kdc", NULL };
+
+            const char * sec_domain_map[] =
+                { "domain_realm", host, NULL };
+
+            char ** values;
+
+            UnicodeStrToAnsi(realm, sizeof(realm),
+                             d->realms[r].realm);
+
+            if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
+                (d->realms[r].flags & K5_RDFLAG_NEW)) {
+
+                khm_size k;
+                khm_size m;
+
+                /* this is a new realm */
+
+                for (k=0; k < d->realms[r].n_kdcs; k++) {
+                    if (!(d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
+                        UnicodeStrToAnsi(host, sizeof(host),
+                                         d->realms[r].kdcs[k].name);
+
+                        if (d->realms[r].kdcs[k].master)
+                            pprofile_add_relation(profile, sec_master,
+                                                  host);
+                        else
+                            pprofile_add_relation(profile, sec_kdcs,
+                                                  host);
+
+                        if (d->realms[r].kdcs[k].admin)
+                            pprofile_add_relation(profile, sec_admin,
+                                                  host);
+
+                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+                    }
+                }
+
+                for (m=0; m < d->realms[r].n_domain_maps; m++) {
+
+                    UnicodeStrToAnsi(host, sizeof(host),
+                                     d->realms[r].domain_maps[m].name);
+
+                    if ((d->realms[r].domain_maps[m].flags &
+                         K5_DMFLAG_DELETED) &&
+                        !(d->realms[r].domain_maps[m].flags &
+                          K5_DMFLAG_NEW)) {
+                        pprofile_clear_relation(profile, sec_domain_map);
+
+                        /* setting this flag indicates that the item
+                           is deleted and not in the profile file
+                           anymore. */
+                        d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+                    } else if (!(d->realms[r].domain_maps[m].flags &
+                               K5_DMFLAG_DELETED) &&
+                             (d->realms[r].domain_maps[m].flags &
+                              K5_DMFLAG_NEW)) {
+                        pprofile_add_relation(profile, sec_domain_map,
+                                              realm);
+
+                        d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+                    }
+                }
+
+                d->realms[r].flags &= ~K5_RDFLAG_NEW;
+
+            } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
+                       !(d->realms[r].flags & K5_RDFLAG_NEW)) {
+
+                const char * sec_all[] =
+                    { "realms", realm, NULL, NULL };
+                khm_size v;
+
+                /* this realm should be deleted */
+
+                rv = pprofile_get_relation_names(profile, sec_all,
+                                                 &values);
+                if (!rv) {
+                    for (v=0; values[v] && values[v][0]; v++) {
+                        sec_all[2] = values[v];
+                        pprofile_clear_relation(profile, sec_all);
+                    }
+                    pprofile_free_list(values);
+                }
+
+                rv = pprofile_get_relation_names(profile, sec_domain_realm,
+                                                 &values);
+                if (!rv) {
+                    char * maprealm;
+
+                    for (v=0; values[v] && values[v][0]; v++) {
+
+                        rv = pprofile_get_string(profile, "domain_realm",
+                                                 values[v], NULL, NULL,
+                                                 &maprealm);
+
+                        if (!rv) {
+                            if (!strcmp(maprealm, realm)) {
+                                StringCbCopyA(host, sizeof(host), 
+                                              values[v]);
+                                pprofile_clear_relation(profile, 
+                                                        sec_domain_map);
+                            }
+                            pprofile_release_string(maprealm);
+                        }
+                    }
+
+                    pprofile_free_list(values);
+                }
+
+                /* setting this flag indicate that the realm is
+                   deleted and is not in the profile file. */
+                d->realms[r].flags |= K5_RDFLAG_NEW;
+
+            } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
+                khm_size k;
+                khm_size m;
+
+                /* same as before.  check if we have to update the kdc
+                   list or the domain_realm mappings */
+
+                for (k=0; k < d->realms[r].n_kdcs; k++) {
+
+                    if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+                        (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED))
+                        continue;
+
+                    UnicodeStrToAnsi(host, sizeof(host),
+                                     d->realms[r].kdcs[k].name);
+
+                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED) {
+                        pprofile_update_relation(profile, sec_kdcs,
+                                                 host, NULL);
+                        pprofile_update_relation(profile, sec_admin,
+                                                 host, NULL);
+                        pprofile_update_relation(profile, sec_master,
+                                                 host, NULL);
+
+                        /* as above, setting 'new' flag to indicate
+                           that the item does not exist in the profile
+                           file. */
+                        d->realms[r].kdcs[k].flags |= K5_RKFLAG_NEW;
+                        continue;
+                    }
+
+                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) {
+                        if (d->realms[r].kdcs[k].master)
+                            pprofile_add_relation(profile, sec_master,
+                                                  host);
+                        else
+                            pprofile_add_relation(profile, sec_kdcs,
+                                                  host);
+
+                        if (d->realms[r].kdcs[k].admin)
+                            pprofile_add_relation(profile, sec_admin,
+                                                  host);
+
+                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+                        continue;
+                    }
+
+                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) {
+                        if (!d->realms[r].kdcs[k].master) {
+                            pprofile_update_relation(profile, sec_kdcs,
+                                                     host, NULL);
+                            pprofile_add_relation(profile, sec_kdcs,
+                                                  host);
+                            pprofile_update_relation(profile, sec_master,
+                                                     host, NULL);
+                        } else {
+                            pprofile_update_relation(profile, sec_master,
+                                                     host, NULL);
+                            pprofile_add_relation(profile, sec_master,
+                                                  host);
+                            pprofile_update_relation(profile, sec_kdcs,
+                                                     host, NULL);
+                        }
+
+                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
+                    }
+
+                    if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_ADMIN) {
+                        if (d->realms[r].kdcs[k].admin) {
+                            pprofile_update_relation(profile, sec_admin,
+                                                     host, NULL);
+                            pprofile_add_relation(profile, sec_admin,
+                                                  host);
+                        } else {
+                            pprofile_update_relation(profile, sec_admin,
+                                                     host, NULL);
+                        }
+
+                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN;
+                    }
+                }
+
+                for (m=0; m < d->realms[r].n_domain_maps; m++) {
+
+                    UnicodeStrToAnsi(host, sizeof(host),
+                                     d->realms[r].domain_maps[m].name);
+
+                    if ((d->realms[r].domain_maps[m].flags &
+                         K5_DMFLAG_DELETED) &&
+
+                        !(d->realms[r].domain_maps[m].flags &
+                          K5_DMFLAG_NEW)) {
+
+                        pprofile_clear_relation(profile, sec_domain_map);
+                        d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+
+                    } else if (!(d->realms[r].domain_maps[m].flags &
+                               K5_DMFLAG_DELETED) &&
+
+                             (d->realms[r].domain_maps[m].flags &
+                              K5_DMFLAG_NEW)) {
+
+                        pprofile_add_relation(profile, sec_domain_map,
+                                              realm);
+                        d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+                    }
+                }
+
+                d->realms[r].flags &= ~K5_RDFLAG_MODIFED;
+            }
+        }
+
+        rv = pprofile_flush(profile);
+
+        pprofile_release(profile);
+    }
+
+    if (rv) {
+        khui_alert * alert;
+        wchar_t title[KHUI_MAXCCH_TITLE];
+        wchar_t fmsg[KHUI_MAXCCH_MESSAGE];
+        wchar_t msg[KHUI_MAXCCH_MESSAGE];
+        wchar_t sugg[KHUI_MAXCCH_SUGGESTION];
+
+        LoadString(hResModule, IDS_K5ERR_CANTWRITEPROFILE,
+                   title, ARRAYLENGTH(title));
+        if (rv)
+            LoadString(hResModule, IDS_K5ERR_PROFNOWRITE,
+                       fmsg, ARRAYLENGTH(fmsg));
+
+        LoadString(hResModule, IDS_K5ERR_PROFSUGGEST,
+                   sugg, ARRAYLENGTH(sugg));
+
+        StringCbPrintf(msg, sizeof(msg), fmsg, config_file);
+
+        khui_alert_create_empty(&alert);
+        khui_alert_set_severity(alert, (rv)?KHERR_ERROR:KHERR_WARNING);
+        khui_alert_set_title(alert, title);
+        khui_alert_set_message(alert, msg);
+        khui_alert_set_suggestion(alert, sugg);
+        
+        khui_alert_show(alert);
+    }
+
+    d->flags = 0;
+}
+
+/* actual dialog stuff */
+
+#define IDX_NORMAL   1
+#define IDX_MODIFIED 2
+#define IDX_NEW      3
+#define IDX_DELETED  4
+
+static k5_config_data k5_config_dlg_data;
+static khm_boolean    k5_dlg_data_valid = FALSE;
+
+INT_PTR CALLBACK 
+k5_config_dlgproc(HWND hwnd,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam) {
+    switch(uMsg) {
+    case WM_INITDIALOG:
+        {
+            HWND hw;
+            khm_size i;
+            k5_config_data * d;
+
+            wchar_t * t;
+            wchar_t importopts[256];
+            WKSTA_INFO_100 * winfo100;
+
+#ifdef DEBUG
+            assert(!k5_dlg_data_valid);
+#endif
+
+            k5_init_config_data(&k5_config_dlg_data);
+            k5_read_config_data(&k5_config_dlg_data);
+
+            k5_dlg_data_valid = TRUE;
+
+            d = &k5_config_dlg_data;
+
+            d->node_main = (khui_config_node) lParam;
+
+            CheckDlgButton(hwnd, IDC_CFG_INCREALMS,
+                           (d->inc_realms)? BST_CHECKED: BST_UNCHECKED);
+
+            hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM);
+#ifdef DEBUG
+            assert(hw);
+#endif
+
+            SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+            for (i=0; i < d->n_realms; i++) {
+                SendMessage(hw, CB_ADDSTRING, 0,
+                            (LPARAM) d->realms[i].realm);
+            }
+
+            SendMessage(hw, CB_SELECTSTRING, -1,
+                        (LPARAM) d->def_realm);
+
+            SetDlgItemText(hwnd, IDC_CFG_CFGFILE, d->config_file);
+
+            /* hostname/domain */
+            if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) {
+                SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername);
+                SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup);
+                NetApiBufferFree(winfo100);
+            }
+
+            /* and the import ticket options */
+            LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS,
+                       importopts, ARRAYLENGTH(importopts));
+
+            hw = GetDlgItem(hwnd, IDC_CFG_IMPORT);
+#ifdef DEBUG
+            assert(hw);
+#endif
+            SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+            for (t=importopts; 
+                 t && *t && *t != L' ' &&
+                     t < importopts + ARRAYLENGTH(importopts);
+                 t = multi_string_next(t)) {
+
+                SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);
+            }
+
+            SendMessage(hw, CB_SETCURSEL, 0, d->lsa_import);
+            t = importopts;
+            SendMessage(hw, CB_GETLBTEXT, d->lsa_import,(LPARAM) t);
+            SendMessage(hw, CB_SELECTSTRING, -1, (LPARAM) t);
+        }
+        break;
+
+    case WM_COMMAND:
+        {
+            k5_config_data * d;
+
+            d = &k5_config_dlg_data;
+
+            if (wParam == MAKEWPARAM(IDC_CFG_IMPORT, CBN_SELCHANGE)) {
+                int idx;
+                int modified = FALSE;
+
+                idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_IMPORT,
+                                               CB_GETCURSEL, 0, 0);
+                if (idx != CB_ERR && idx != d->lsa_import) {
+                    d->lsa_import = idx;
+                    d->flags |= K5_CDFLAG_MOD_LSA_IMPORT;
+                    modified = TRUE;
+                }
+
+                khui_cfg_set_flags(d->node_main,
+                                   (modified)?KHUI_CNFLAG_MODIFIED:0,
+                                   KHUI_CNFLAG_MODIFIED);
+                return TRUE;
+            }
+
+            if (wParam == MAKEWPARAM(IDC_CFG_INCREALMS, BN_CLICKED)) {
+                if (IsDlgButtonChecked(hwnd, IDC_CFG_INCREALMS) ==
+                    BST_CHECKED) {
+                    d->inc_realms = TRUE;
+                } else {
+                    d->inc_realms = FALSE;
+                }
+                d->flags |= K5_CDFLAG_MOD_INC_REALMS;
+
+                khui_cfg_set_flags(d->node_main,
+                                   KHUI_CNFLAG_MODIFIED,
+                                   KHUI_CNFLAG_MODIFIED);
+                return TRUE;
+            }
+        }
+        break;
+
+    case KHUI_WM_CFG_NOTIFY:
+        {
+            k5_config_data * d;
+
+            d = &k5_config_dlg_data;
+
+            if (HIWORD(wParam) == WMCFG_APPLY) {
+                khm_int32 oflags;
+
+                oflags = d->flags;
+                k5_write_config_data(d);
+
+                if (d->flags != oflags) {
+                    khui_cfg_set_flags(d->node_main,
+                                       KHUI_CNFLAG_APPLIED,
+                                       KHUI_CNFLAG_APPLIED |
+                                       KHUI_CNFLAG_MODIFIED);
+                }
+                return TRUE;
+            }
+        }
+        break;
+
+    case WM_DESTROY:
+        {
+            k5_free_config_data(&k5_config_dlg_data);
+            k5_dlg_data_valid = FALSE;
+        }
+        break;
+    }
+    return FALSE;
+}
+
+static HIMAGELIST
+k5_get_state_image_list(void) {
+    HIMAGELIST hil;
+    HICON hicon;
+
+    hil = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+                           GetSystemMetrics(SM_CYSMICON),
+                           ILC_COLOR | ILC_MASK,
+                           4,
+                           2);
+
+    hicon = LoadImage(hResModule,
+                      MAKEINTRESOURCE(IDI_NORMAL),
+                      IMAGE_ICON,
+                      GetSystemMetrics(SM_CXSMICON),
+                      GetSystemMetrics(SM_CYSMICON),
+                      LR_DEFAULTCOLOR);
+
+    ImageList_AddIcon(hil, hicon);
+
+    DestroyIcon(hicon);
+
+    hicon = LoadImage(hResModule,
+                      MAKEINTRESOURCE(IDI_MODIFIED),
+                      IMAGE_ICON,
+                      GetSystemMetrics(SM_CXSMICON),
+                      GetSystemMetrics(SM_CYSMICON),
+                      LR_DEFAULTCOLOR);
+
+    ImageList_AddIcon(hil, hicon);
+
+    DestroyIcon(hicon);
+
+    hicon = LoadImage(hResModule,
+                      MAKEINTRESOURCE(IDI_NEW),
+                      IMAGE_ICON,
+                      GetSystemMetrics(SM_CXSMICON),
+                      GetSystemMetrics(SM_CYSMICON),
+                      LR_DEFAULTCOLOR);
+
+    ImageList_AddIcon(hil, hicon);
+
+    DestroyIcon(hicon);
+
+    hicon = LoadImage(hResModule,
+                      MAKEINTRESOURCE(IDI_DELETED),
+                      IMAGE_ICON,
+                      GetSystemMetrics(SM_CXSMICON),
+                      GetSystemMetrics(SM_CYSMICON),
+                      LR_DEFAULTCOLOR);
+
+    ImageList_AddIcon(hil, hicon);
+
+    DestroyIcon(hicon);
+
+    return hil;
+}
+
+static void
+k5_update_realms_display(HWND hw_list, k5_config_data * d) {
+    khm_size i;
+    LVITEM lvi;
+    wchar_t buf[64];
+
+    ListView_DeleteAllItems(hw_list);
+
+    for (i=0; i < d->n_realms; i++) {
+        if ((d->realms[i].flags & K5_RDFLAG_DELETED) &&
+            (d->realms[i].flags & K5_RDFLAG_NEW))
+            continue;
+
+        ZeroMemory(&lvi, sizeof(lvi));
+        lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+        lvi.iItem = 0;
+        lvi.iSubItem = 0;
+        lvi.pszText = d->realms[i].realm;
+        lvi.lParam = i;
+
+        if (d->realms[i].flags & K5_RDFLAG_DELETED) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+        } else if (d->realms[i].flags & K5_RDFLAG_NEW) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+        } else if (d->realms[i].flags & K5_RDFLAG_MODIFED) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
+        } else {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+        }
+        lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+        ListView_InsertItem(hw_list, &lvi);
+    }
+
+    ZeroMemory(&lvi, sizeof(lvi));
+    lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+    lvi.iItem = 0;
+    lvi.iSubItem = 0;
+    lvi.pszText = buf;
+    lvi.lParam = (LPARAM) -1;
+
+    LoadString(hResModule, IDS_CFG_RE_NEWREALM,
+               buf, ARRAYLENGTH(buf));
+
+    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+    lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+    ListView_InsertItem(hw_list, &lvi);
+
+    if (d->flags & K5_CDFLAG_MOD_REALMS) {
+        khui_cfg_set_flags(d->node_realm, KHUI_CNFLAG_MODIFIED,
+                           KHUI_CNFLAG_MODIFIED);
+    } else {
+        khui_cfg_set_flags(d->node_realm, 0,
+                           KHUI_CNFLAG_MODIFIED);
+    }
+}
+
+#define K5_KDCSI_ADMIN 1
+#define K5_KDCSI_MASTER 2
+
+static void
+k5_update_kdcs_display(HWND hw_kdc, k5_config_data * d, khm_size idx_rlm) {
+    khm_size k;
+    LVITEM lvi;
+    int idx_item;
+    k5_realm_kdc * pkdc;
+    wchar_t wyes[8];
+    wchar_t wno[8];
+    wchar_t wbuf[64];
+
+    ListView_DeleteAllItems(hw_kdc);
+
+    if (d == NULL)
+        return;
+
+#ifdef DEBUG
+    assert(idx_rlm < d->n_realms);
+#endif
+    LoadString(hResModule, IDS_YES, wyes, ARRAYLENGTH(wyes));
+    LoadString(hResModule, IDS_NO, wno, ARRAYLENGTH(wno));
+
+    for (k=0; k < d->realms[idx_rlm].n_kdcs; k++) {
+        if ((d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_DELETED) &&
+            (d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_NEW))
+            continue;
+
+        pkdc = &(d->realms[idx_rlm].kdcs[k]);
+
+        ZeroMemory(&lvi, sizeof(lvi));
+        lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+        lvi.iItem = K5_MAX_KDC;
+        lvi.iSubItem = 0;
+        lvi.lParam = k;
+        lvi.pszText = pkdc->name;
+        if (pkdc->flags & K5_RKFLAG_DELETED) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+        } else if (pkdc->flags & K5_RKFLAG_NEW) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+        } else if ((pkdc->flags & K5_RKFLAG_MOD_ADMIN) ||
+                   (pkdc->flags & K5_RKFLAG_MOD_MASTER)) {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
+        } else {
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+        }
+        lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+        idx_item = ListView_InsertItem(hw_kdc, &lvi);
+
+        lvi.mask = LVIF_TEXT;
+        lvi.iItem = idx_item;
+        lvi.iSubItem = K5_KDCSI_ADMIN;
+        if (pkdc->admin)
+            lvi.pszText = wyes;
+        else
+            lvi.pszText = wno;
+        ListView_SetItem(hw_kdc, &lvi);
+
+        lvi.iSubItem = K5_KDCSI_MASTER;
+        if (pkdc->master)
+            lvi.pszText = wyes;
+        else
+            lvi.pszText = wno;
+        ListView_SetItem(hw_kdc, &lvi);
+    }
+
+    ZeroMemory(&lvi, sizeof(lvi));
+    lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+    lvi.iItem = 0;
+    lvi.iSubItem = 0;
+    lvi.pszText = wbuf;
+    lvi.lParam = (LPARAM) -1;
+    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+    lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+    LoadString(hResModule, IDS_CFG_RE_NEWSERVER,
+               wbuf, ARRAYLENGTH(wbuf));
+
+    ListView_InsertItem(hw_kdc, &lvi);
+}
+
+static void
+k5_update_dmap_display(HWND hw_dm, k5_config_data * d, khm_size idx_rlm) {
+    khm_size m;
+    LVITEM lvi;
+    k5_domain_map * map;
+    wchar_t wbuf[64];
+
+    ListView_DeleteAllItems(hw_dm);
+
+    if (d == NULL)
+        return;
+
+#ifdef DEBUG
+    assert(idx_rlm < d->n_realms);
+#endif
+
+    for (m=0; m < d->realms[idx_rlm].n_domain_maps; m++) {
+        map = &(d->realms[idx_rlm].domain_maps[m]);
+
+        if ((map->flags & K5_DMFLAG_NEW) &&
+            (map->flags & K5_DMFLAG_DELETED))
+            continue;
+
+        ZeroMemory(&lvi, sizeof(lvi));
+
+        lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
+        lvi.pszText = map->name;
+        if (map->flags & K5_DMFLAG_DELETED)
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+        else if (map->flags & K5_DMFLAG_NEW)
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+        else
+            lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+        lvi.stateMask = LVIS_STATEIMAGEMASK;
+        lvi.lParam = m;
+
+        lvi.iItem = K5_MAX_DOMAIN_MAPPINGS;
+        lvi.iSubItem = 0;
+
+        ListView_InsertItem(hw_dm, &lvi);
+    }
+
+    ZeroMemory(&lvi, sizeof(lvi));
+    lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
+    lvi.pszText = wbuf;
+    lvi.lParam = (LPARAM) -1;
+    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+    lvi.stateMask = LVIS_STATEIMAGEMASK;
+    lvi.iItem = 0;
+    lvi.iSubItem = 0;
+
+    LoadString(hResModule, IDS_CFG_RE_NEWDMAP,
+               wbuf, ARRAYLENGTH(wbuf));
+
+    ListView_InsertItem(hw_dm, &lvi);
+}
+
+#define CMD_BASE 3000
+#define CMD_NEW_REALM    (CMD_BASE + 1)
+#define CMD_DEL_REALM    (CMD_BASE + 2)
+#define CMD_NEW_SERVER   (CMD_BASE + 3)
+#define CMD_DEL_SERVER   (CMD_BASE + 4)
+#define CMD_MAKE_ADMIN   (CMD_BASE + 5)
+#define CMD_MAKE_MASTER  (CMD_BASE + 6)
+#define CMD_NEW_DMAP     (CMD_BASE + 7)
+#define CMD_DEL_DMAP     (CMD_BASE + 8)
+
+struct k5_menu_def {
+    UINT string;
+    UINT id;
+    UINT type;
+    UINT state;
+};
+
+struct k5_menu_def k5_menu_realms[] = {
+    {IDS_CFG_RE_MNR, CMD_NEW_REALM, MFT_STRING, 0},
+    {IDS_CFG_RE_MDR, CMD_DEL_REALM, MFT_STRING, 0}
+};
+
+struct k5_menu_def k5_menu_kdc[] = {
+    {IDS_CFG_RE_MNK, CMD_NEW_SERVER, MFT_STRING, 0},
+    {IDS_CFG_RE_MDK, CMD_DEL_SERVER, MFT_STRING, 0},
+    {IDS_CFG_RE_MAK, CMD_MAKE_ADMIN, MFT_STRING, 0},
+    {IDS_CFG_RE_MMK, CMD_MAKE_MASTER, MFT_STRING, 0}
+};
+
+struct k5_menu_def k5_menu_dmap[] = {
+    {IDS_CFG_RE_MND, CMD_NEW_DMAP, MFT_STRING, 0},
+    {IDS_CFG_RE_MDD, CMD_DEL_DMAP, MFT_STRING, 0}
+};
+
+HMENU
+k5_menu_from_def(struct k5_menu_def * def, khm_size n) {
+    HMENU menu;
+    MENUITEMINFO mii;
+    khm_size i;
+    khm_size cch;
+    wchar_t buf[1024];
+
+    menu = CreatePopupMenu();
+
+    for (i=0; i < n; i++) {
+        ZeroMemory(&mii, sizeof(mii));
+
+        mii.cbSize = sizeof(mii);
+
+        if (def[i].type == MFT_STRING) {
+            LoadString(hResModule, def[i].string,
+                       buf, ARRAYLENGTH(buf));
+            StringCchLength(buf, ARRAYLENGTH(buf), &cch);
+
+            mii.fMask = MIIM_STRING | MIIM_ID;
+            mii.fType = MFT_STRING;
+
+            mii.fState = def[i].state;
+            mii.wID = def[i].id;
+            mii.cch = (UINT) cch;
+            mii.dwTypeData = buf;
+
+            InsertMenuItem(menu, (UINT) i, TRUE, &mii);
+        } else {
+#ifdef DEBUG
+            assert(FALSE);
+#endif
+        }
+    }
+
+    return menu;
+}
+
+void
+k5_delete_realms(HWND hwnd, k5_config_data * d) {
+    LVITEM lvi;
+    int idx;
+    HWND hw_rlm;
+    BOOL modified = FALSE;
+    khm_size r;
+
+    hw_rlm = GetDlgItem(hwnd, IDC_CFG_REALMS);
+
+    idx = -1;
+    while((idx = ListView_GetNextItem(hw_rlm, idx,
+                                      LVNI_SELECTED))
+          != -1) {
+        ZeroMemory(&lvi, sizeof(lvi));
+        lvi.iItem = idx;
+        lvi.iSubItem = 0;
+        lvi.mask = LVIF_PARAM;
+        
+        ListView_GetItem(hw_rlm, &lvi);
+
+        if (lvi.lParam != -1 &&
+            (r = lvi.lParam) < d->n_realms) {
+            d->realms[r].flags ^= K5_RDFLAG_DELETED;
+            modified = TRUE;
+        }
+    }
+
+    if (modified) {
+        d->flags |= K5_CDFLAG_MOD_REALMS;
+        
+        k5_purge_config_data(d, TRUE, TRUE, TRUE);
+        k5_update_realms_display(hw_rlm, d);
+        k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
+        k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
+    }
+}
+
+void
+k5_delete_servers(HWND hwnd, k5_config_data * d) {
+    HWND hw_kdc;
+    LVITEM lvi;
+    khm_size r;
+    khm_size k;
+    int idx;
+    BOOL modified = FALSE;
+
+    hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+    r = d->c_realm;
+    
+    idx = -1;
+    while((idx = ListView_GetNextItem(hw_kdc, idx,
+                                      LVNI_SELECTED))
+          != -1) {
+        ZeroMemory(&lvi, sizeof(lvi));
+        lvi.iItem = idx;
+        lvi.iSubItem = 0;
+        lvi.mask = LVIF_PARAM;
+
+        ListView_GetItem(hw_kdc, &lvi);
+
+        if (lvi.lParam != -1 &&
+            (k = lvi.lParam) < d->n_realms) {
+            d->realms[r].kdcs[k].flags ^= K5_RKFLAG_DELETED;
+            modified = TRUE;
+        }
+    }
+
+    if (modified) {
+        d->flags |= K5_CDFLAG_MOD_REALMS;
+        d->realms[r].flags |= K5_RDFLAG_MODIFED;
+        
+        k5_purge_config_data(d, TRUE, TRUE, TRUE);
+        k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+        k5_update_kdcs_display(hw_kdc, d, r);
+    }
+}
+
+void
+k5_delete_dmap(HWND hwnd, k5_config_data * d) {
+    HWND hw_dmp;
+    LVITEM lvi;
+    khm_size r;
+    khm_size m;
+    int idx;
+    BOOL modified = FALSE;
+
+    hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);
+    r = d->c_realm;
+
+    idx = -1;
+    while((idx = ListView_GetNextItem(hw_dmp, idx,
+                                      LVNI_SELECTED))
+          != -1) {
+        ZeroMemory(&lvi, sizeof(lvi));
+        lvi.iItem = idx;
+        lvi.iSubItem = 0;
+        lvi.mask = LVIF_PARAM;
+        
+        ListView_GetItem(hw_dmp, &lvi);
+
+        if (lvi.lParam != -1 &&
+            (m = lvi.lParam) < d->n_realms) {
+            d->realms[r].domain_maps[m].flags ^= K5_DMFLAG_DELETED;
+            modified = TRUE;
+        }
+    }
+
+    if (modified) {
+        d->flags |= K5_CDFLAG_MOD_REALMS;
+        k5_purge_config_data(d, FALSE, FALSE, TRUE);
+        
+        if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+            d->realms[r].flags |= K5_RDFLAG_MODIFED;
+
+            k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+        }
+
+        k5_update_dmap_display(hw_dmp, d, r);
+    }
+}
+
+INT_PTR CALLBACK 
+k5_realms_dlgproc(HWND hwnd,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam) {
+    k5_config_data * d;
+
+    d = &k5_config_dlg_data;
+
+    switch(uMsg) {
+    case WM_INITDIALOG:
+        {
+            LVCOLUMN lvc;
+            HWND hw;
+            RECT r;
+            wchar_t buf[256];
+
+            assert(k5_dlg_data_valid);
+
+            d->node_realm = (khui_config_node) lParam;
+
+            /* set up columns for the Realms list */
+            hw = GetDlgItem(hwnd, IDC_CFG_REALMS);
+#ifdef DEBUG
+            assert(hw);
+#endif
+            GetWindowRect(hw, &r);
+            r.right -= 5;       /* shave a few pixels off the width */
+            ZeroMemory(&lvc, sizeof(lvc));
+            lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+            lvc.pszText = buf;
+            lvc.cx = (r.right - r.left);
+            LoadString(hResModule, IDS_CFG_RE_REALMS,
+                       buf, ARRAYLENGTH(buf));
+
+            ListView_InsertColumn(hw, 0, &lvc);
+
+            ListView_SetImageList(hw,
+                                  k5_get_state_image_list(),
+                                  LVSIL_STATE);
+
+            k5_update_realms_display(hw, d);
+
+            /* set up columns for the servers list */
+            hw = GetDlgItem(hwnd, IDC_CFG_KDC);
+#ifdef DEBUG
+            assert(hw);
+#endif
+            GetWindowRect(hw, &r);
+            r.right -= 5;
+            ZeroMemory(&lvc, sizeof(lvc));
+            lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+            lvc.pszText = buf;
+            lvc.cx = (r.right - r.left) * 2 / 4;
+            LoadString(hResModule, IDS_CFG_RE_HEAD_SVR,
+                       buf, ARRAYLENGTH(buf));
+
+            ListView_InsertColumn(hw, 0, &lvc);
+
+            lvc.cx = (r.right - r.left) * 1 / 4;
+            LoadString(hResModule, IDS_CFG_RE_HEAD_ADMIN,
+                       buf, ARRAYLENGTH(buf));
+            ListView_InsertColumn(hw, 1, &lvc);
+
+            LoadString(hResModule, IDS_CFG_RE_HEAD_MASTER,
+                       buf, ARRAYLENGTH(buf));
+            ListView_InsertColumn(hw, 2, &lvc);
+
+            ListView_SetImageList(hw,
+                                  k5_get_state_image_list(),
+                                  LVSIL_STATE);
+
+            /* set up columns for the domain/host mapping list */
+            hw = GetDlgItem(hwnd, IDC_CFG_DMAP);
+#ifdef DEBUG
+            assert(hw);
+#endif
+            GetWindowRect(hw, &r);
+            r.right -= 5;
+            ZeroMemory(&lvc, sizeof(lvc));
+            lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+            lvc.pszText = buf;
+            lvc.cx = (r.right - r.left);
+            LoadString(hResModule, IDS_CFG_RE_HEAD_DOMAIN,
+                       buf, ARRAYLENGTH(buf));
+
+            ListView_InsertColumn(hw, 0, &lvc);
+
+
+            ListView_SetImageList(hw,
+                                  k5_get_state_image_list(),
+                                  LVSIL_STATE);
+
+            /* Now set up the context menus */
+            d->hm_realms_ctx = k5_menu_from_def(k5_menu_realms, ARRAYLENGTH(k5_menu_realms));
+            d->hm_kdc_ctx = k5_menu_from_def(k5_menu_kdc, ARRAYLENGTH(k5_menu_kdc));
+            d->hm_dmap_ctx = k5_menu_from_def(k5_menu_dmap, ARRAYLENGTH(k5_menu_dmap));
+        }
+        break;
+
+    case WM_CONTEXTMENU:
+        {
+            UINT id;
+            HMENU hm = NULL;
+            int x,y;
+
+            id = GetDlgCtrlID((HWND) wParam);
+
+            if (id == IDC_CFG_REALMS) {
+                HWND hw_realms;
+                int n;
+                MENUITEMINFO mii;
+
+                hm = d->hm_realms_ctx;
+
+                hw_realms = GetDlgItem(hwnd, IDC_CFG_REALMS);
+#ifdef DEBUG
+                assert(hw_realms);
+#endif
+                n = ListView_GetSelectedCount(hw_realms);
+                ZeroMemory(&mii, sizeof(mii));
+                mii.cbSize = sizeof(mii);
+
+                if (n == 0) {
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_DISABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii);
+                } else {
+
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_ENABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii);
+                }
+                
+            } else if (id == IDC_CFG_KDC) {
+                HWND hw_kdc;
+                int n;
+                MENUITEMINFO mii;
+
+                hm = d->hm_kdc_ctx;
+
+                hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+#ifdef DEBUG
+                assert(hw_kdc);
+#endif
+                n = ListView_GetSelectedCount(hw_kdc);
+                ZeroMemory(&mii, sizeof(mii));
+                mii.cbSize = sizeof(mii);
+
+                if (n == 1) {
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_ENABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+                    SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+                    SetMenuItemInfo(hm, CMD_MAKE_MASTER, FALSE, &mii);
+                } else if (n == 0) {
+
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_DISABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+                    SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+                    SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii);
+                } else {
+
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_ENABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+                    
+                    mii.fState = MFS_DISABLED;
+
+                    SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+                    SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii);
+                }
+
+            } else if (id == IDC_CFG_DMAP) {
+                HWND hw_dmap;
+                MENUITEMINFO mii;
+                int n;
+
+                hm = d->hm_dmap_ctx;
+
+                hw_dmap = GetDlgItem(hwnd, IDC_CFG_DMAP);
+#ifdef DEBUG
+                assert(hw_dmap);
+#endif
+
+                n = ListView_GetSelectedCount(hw_dmap);
+                ZeroMemory(&mii, sizeof(mii));
+                mii.cbSize = sizeof(mii);
+
+                if (n == 0) {
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_DISABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii);
+                } else {
+                    mii.fMask = MIIM_STATE;
+                    mii.fState = MFS_ENABLED;
+
+                    SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii);
+                }
+            }
+
+            if (hm) {
+                if (LOWORD(lParam) == 0xffff) {
+                    HWND hw;
+                    RECT r;
+
+                    hw = GetDlgItem(hwnd, id);
+#ifdef DEBUG
+                    assert(hw);
+#endif
+                    GetWindowRect(hw, &r);
+                    x = r.left;
+                    y = r.top;
+                } else {
+                    x = LOWORD(lParam);
+                    y = HIWORD(lParam);
+                }
+
+                TrackPopupMenu(hm,
+                               TPM_LEFTALIGN | TPM_TOPALIGN,
+                               x, y,
+                               0, hwnd, NULL);
+            }
+
+            return TRUE;
+        }
+        break;
+
+    case WM_NOTIFY:
+        {
+            LPNMHDR pnmh;
+            HWND hw_rlm = NULL;
+            HWND hw_kdc = NULL;
+            HWND hw_dmp = NULL;
+            int i;
+
+            pnmh = (LPNMHDR) lParam;
+
+            /* catchalls for all three list views */
+            switch (pnmh->code) {
+            case NM_DBLCLK:
+                {
+                    HWND hw_ctl;
+                    LVITEM lvi;
+                    LVHITTESTINFO hti;
+                    LPNMITEMACTIVATE pnmi;
+
+                    if (pnmh->idFrom != IDC_CFG_REALMS &&
+                        pnmh->idFrom != IDC_CFG_KDC &&
+                        pnmh->idFrom != IDC_CFG_DMAP)
+                        break;
+
+                    /* if the user double clicks on the 'new
+                       [something]' item, we start editing it. */
+                    hw_ctl = pnmh->hwndFrom;
+                    pnmi = (LPNMITEMACTIVATE) lParam;
+
+                    ZeroMemory(&hti, sizeof(hti));
+                    hti.pt = pnmi->ptAction;
+
+                    ListView_SubItemHitTest(hw_ctl, &hti);
+                    if (hti.flags & LVHT_ONITEM) {
+                        ZeroMemory(&lvi, sizeof(lvi));
+                        lvi.mask = LVIF_PARAM;
+                        lvi.iItem = hti.iItem;
+
+                        ListView_GetItem(hw_ctl, &lvi);
+
+                        if (lvi.lParam == -1)
+                            ListView_EditLabel(hw_ctl, hti.iItem);
+                    }
+
+                    return TRUE;
+                }
+                break;
+            }
+
+            if (pnmh->idFrom == IDC_CFG_REALMS) {
+
+                hw_rlm = pnmh->hwndFrom;
+
+                switch(pnmh->code) {
+                case LVN_ITEMCHANGED:
+                    i = ListView_GetSelectedCount(hw_rlm);
+                    hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+                    hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);
+
+                    d->c_realm = (khm_size) -1;
+
+                    if (i == 1) {
+                        LVITEM lvi;
+                        wchar_t fmt[256];
+                        wchar_t buf[K5_MAXCCH_REALM + 256];
+
+                        i = ListView_GetNextItem(hw_rlm, -1,
+                                                 LVNI_SELECTED);
+                        if (i == -1)
+                            goto _no_selection;
+
+                        ZeroMemory(&lvi, sizeof(lvi));
+
+                        lvi.iItem = i;
+                        lvi.iSubItem = 0;
+                        lvi.mask = LVIF_PARAM;
+
+                        ListView_GetItem(hw_rlm, &lvi);
+
+                        if (lvi.lParam == -1)
+                            goto _no_selection;
+
+                        d->c_realm = lvi.lParam;
+
+                        k5_update_kdcs_display(hw_kdc, d, lvi.lParam);
+                        k5_update_dmap_display(hw_dmp, d, lvi.lParam);
+
+                        LoadString(hResModule, IDS_CFG_RE_KDCS_R,
+                                   fmt, ARRAYLENGTH(fmt));
+                        StringCbPrintf(buf, sizeof(buf), fmt,
+                                       d->realms[d->c_realm].realm);
+
+                        SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf);
+
+                        LoadString(hResModule, IDS_CFG_RE_DMAPS_R,
+                                   fmt, ARRAYLENGTH(fmt));
+                        StringCbPrintf(buf, sizeof(buf), fmt,
+                                       d->realms[d->c_realm].realm);
+
+                        SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf);
+                        return TRUE;
+                    }
+
+                _no_selection:
+                    {
+                        wchar_t buf[256];
+
+                        k5_update_kdcs_display(hw_kdc, NULL, 0);
+                        k5_update_dmap_display(hw_dmp, NULL, 0);
+
+                        LoadString(hResModule, IDS_CFG_RE_KDCS,
+                                   buf, ARRAYLENGTH(buf));
+                        SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf);
+
+                        LoadString(hResModule, IDS_CFG_RE_DMAPS,
+                                   buf, ARRAYLENGTH(buf));
+                        SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf);
+                    }
+                    break;
+
+                case LVN_BEGINLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        LVITEM lvi;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        ZeroMemory(&lvi, sizeof(lvi));
+                        lvi.iItem = pdisp->item.iItem;
+                        lvi.mask = LVIF_PARAM;
+
+                        ListView_GetItem(hw_rlm, &lvi);
+
+                        if (pdisp->item.iItem == -1 ||
+                            lvi.lParam != -1) {
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+                        } else {
+                            /* allow editing */
+                            HWND hw_edit;
+
+                            hw_edit = ListView_GetEditControl(hw_rlm);
+                            if (hw_edit != NULL) {
+                                SendMessage(hw_edit,
+                                            EM_SETLIMITTEXT,
+                                            K5_MAXCCH_REALM - 1,
+                                            0);
+                            }
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                        }
+
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_ENDLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        khm_size n;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+                            khm_size i;
+
+                            /* first find out whether this is actually
+                               a new realm */
+
+                            for (i=0; i < d->n_realms; i++) {
+                                if ((d->realms[i].flags & K5_RDFLAG_NEW) &&
+                                    (d->realms[i].flags & K5_RDFLAG_DELETED))
+                                    continue;
+
+                                if (!wcsicmp(d->realms[i].realm, pdisp->item.pszText))
+                                    break;
+                            }
+
+                            if (i < d->n_realms) {
+                                khui_alert * alert = NULL;
+                                wchar_t buf[KHUI_MAXCCH_MESSAGE];
+                                wchar_t fmt[KHUI_MAXCCH_MESSAGE];
+
+                                khui_alert_create_empty(&alert);
+
+                                LoadString(hResModule, IDS_CFG_RE_ARNUT,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText);
+                                khui_alert_set_title(alert, buf);
+
+                                LoadString(hResModule, IDS_CFG_RE_ARNUM,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText);
+                                khui_alert_set_message(alert, buf);
+
+                                khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
+                                khui_alert_set_severity(alert, KHERR_INFO);
+
+                                khui_alert_show_modal(alert);
+                                khui_alert_release(alert);
+
+                                return TRUE;
+                            }
+
+                            n = d->n_realms;
+                            k5_assert_n_realms(d, n+1);
+                            StringCbCopy(d->realms[n].realm,
+                                         sizeof(d->realms[n].realm),
+                                         pdisp->item.pszText);
+                            d->realms[n].flags = K5_RDFLAG_NEW;
+                            d->n_realms++;
+
+                            d->flags |= K5_CDFLAG_MOD_REALMS;
+
+                            k5_update_realms_display(hw_rlm, d);
+                        }
+
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_KEYDOWN:
+                    {
+                        NMLVKEYDOWN * pnmk;
+
+                        pnmk = (NMLVKEYDOWN *) lParam;
+
+                        if (pnmk->wVKey == VK_DELETE) {
+                            k5_delete_realms(hwnd, d);
+                            return TRUE;
+                        }
+                    }
+                    break;
+                }
+            } else if (pnmh->idFrom == IDC_CFG_KDC) {
+                hw_kdc = pnmh->hwndFrom;
+
+                switch (pnmh->code) {
+                case LVN_BEGINLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        LVITEM lvi;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        ZeroMemory(&lvi, sizeof(lvi));
+                        lvi.iItem = pdisp->item.iItem;
+                        lvi.mask = LVIF_PARAM;
+
+                        ListView_GetItem(hw_kdc, &lvi);
+
+                        /* Only allow editing if the user is trying to
+                           edit the <New server> entry. */
+                        if (pdisp->item.iItem == -1 ||
+                            lvi.lParam != -1) {
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+                        } else {
+                            HWND hw_edit;
+
+                            hw_edit = ListView_GetEditControl(hw_kdc);
+                            if (hw_edit != NULL) {
+                                SendMessage(hw_edit,
+                                            EM_SETLIMITTEXT,
+                                            K5_MAXCCH_HOST - 1,
+                                            0);
+                            }
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                        }
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_ENDLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        khm_size r;
+                        khm_size k;
+
+                        r = d->c_realm;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+
+                            /* first of all, check if we already have
+                               a KDC by this name... */
+                            for (k=0; k < d->realms[r].n_kdcs; k++) {
+                                if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+                                    (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED))
+                                    continue;
+
+                                if (!wcsicmp(d->realms[r].kdcs[k].name,
+                                             pdisp->item.pszText))
+                                    break;
+                            }
+
+                            if (k < d->realms[r].n_kdcs) {
+                                khui_alert * alert = NULL;
+                                wchar_t buf[K5_MAXCCH_HOST + 256];
+                                wchar_t fmt[256];
+
+                                khui_alert_create_empty(&alert);
+
+                                LoadString(hResModule, IDS_CFG_RE_ASNUT,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText,
+                                               d->realms[r].realm);
+                                khui_alert_set_title(alert, buf);
+
+                                LoadString(hResModule, IDS_CFG_RE_ASNUM,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText,
+                                               d->realms[r].realm);
+                                khui_alert_set_message(alert, buf);
+
+                                khui_alert_set_severity(alert, KHERR_INFO);
+                                khui_alert_show_modal(alert);
+
+                                khui_alert_release(alert);
+
+                                SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                                return TRUE;
+                            }
+
+                            if (k >= K5_MAX_KDC) {
+                                SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                                /* TODO: show a message box saying
+                                   there are too many KDC's
+                                   already. */
+                                return TRUE;
+                            }
+
+                            StringCbCopy(d->realms[r].kdcs[k].name,
+                                         sizeof(d->realms[0].kdcs[0].name),
+                                         pdisp->item.pszText);
+                            d->realms[r].kdcs[k].flags = K5_RKFLAG_NEW;
+                            d->realms[r].n_kdcs++;
+
+                            k5_update_kdcs_display(hw_kdc, d, d->c_realm);
+
+                            if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+                                d->flags |= K5_CDFLAG_MOD_REALMS;
+                                d->realms[r].flags |= K5_RDFLAG_MODIFED;
+                                k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+                            }
+                        }
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_KEYDOWN:
+                    {
+                        NMLVKEYDOWN * pnmk;
+
+                        pnmk = (NMLVKEYDOWN *) lParam;
+
+                        if (pnmk->wVKey == VK_DELETE) {
+                            k5_delete_servers(hwnd, d);
+                        }
+                        return TRUE;
+                    }
+                    break;
+
+                case NM_CLICK:
+                    {
+                        LPNMITEMACTIVATE lpnmi;
+                        LVHITTESTINFO hti;
+                        LVITEM lvi;
+                        khm_size r;
+                        khm_size k;
+
+                        r = d->c_realm;
+
+                        lpnmi = (LPNMITEMACTIVATE) lParam;
+
+                        ZeroMemory(&hti, sizeof(hti));
+                        hti.pt = lpnmi->ptAction;
+                        ListView_SubItemHitTest(hw_kdc, &hti);
+
+                        if (hti.iSubItem != 0) {
+
+                            ZeroMemory(&lvi, sizeof(lvi));
+
+                            lvi.mask = LVIF_PARAM;
+                            lvi.iItem = hti.iItem;
+                            ListView_GetItem(hw_kdc, &lvi);
+
+                            if (lvi.lParam < 0 || lvi.lParam >= (int) d->realms[r].n_kdcs)
+                                return TRUE;
+
+                            k = lvi.lParam;
+
+                            if (hti.iSubItem == K5_KDCSI_ADMIN) {
+                                d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin;
+                                d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN;
+                            } else if (hti.iSubItem == K5_KDCSI_MASTER) {
+                                if (d->realms[r].kdcs[k].master) {
+                                    d->realms[r].kdcs[k].master = FALSE;
+                                    d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+                                } else {
+                                    khm_size i;
+
+                                    for (i=0; i < d->realms[r].n_kdcs; i++) {
+                                        if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED) &&
+                                            (d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW))
+                                            continue;
+                                        if (d->realms[r].kdcs[i].master) {
+                                            d->realms[r].kdcs[i].master = FALSE;
+                                            d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER;
+                                        }
+                                    }
+
+                                    d->realms[r].kdcs[k].master = TRUE;
+                                    d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+                                }
+                            } else {
+#ifdef DEBUG
+                                assert(FALSE);
+#endif
+                            }
+
+                            if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+                                d->realms[r].flags |= K5_RDFLAG_MODIFED;
+                                d->flags |= K5_CDFLAG_MOD_REALMS;
+                                k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+                            }
+
+                            k5_update_kdcs_display(hw_kdc, d, r);
+                        }
+                    }
+                    break;
+                }
+            } else if (pnmh->idFrom == IDC_CFG_DMAP) {
+                hw_dmp = pnmh->hwndFrom;
+
+                switch (pnmh->code) {
+                case LVN_BEGINLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        LVITEM lvi;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        ZeroMemory(&lvi, sizeof(lvi));
+                        lvi.iItem = pdisp->item.iItem;
+                        lvi.mask = LVIF_PARAM;
+
+                        ListView_GetItem(hw_dmp, &lvi);
+
+                        /* Only allow editing if the user is trying to
+                           edit the <New domain mapping> entry. */
+                        if (pdisp->item.iItem == -1 ||
+                            lvi.lParam != -1) {
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+                        } else {
+                            HWND hw_edit;
+
+                            hw_edit = ListView_GetEditControl(hw_dmp);
+                            if (hw_edit != NULL) {
+                                SendMessage(hw_edit,
+                                            EM_SETLIMITTEXT,
+                                            K5_MAXCCH_HOST - 1,
+                                            0);
+                            }
+                            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                        }
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_ENDLABELEDIT:
+                    {
+                        NMLVDISPINFO * pdisp;
+                        khm_size r;
+                        khm_size m;
+
+                        r = d->c_realm;
+
+                        pdisp = (NMLVDISPINFO *) lParam;
+
+                        if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+
+                            /* first check if this is unique */
+                            for (m=0; m < d->realms[r].n_domain_maps; m++) {
+                                if ((d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&
+                                    (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED))
+                                    continue;
+
+                                if (!wcsicmp(d->realms[r].domain_maps[m].name,
+                                             pdisp->item.pszText))
+                                    break;
+                            }
+
+                            if (m < d->realms[r].n_domain_maps) {
+                                khui_alert * alert;
+                                wchar_t buf[K5_MAXCCH_HOST + 256];
+                                wchar_t fmt[256];
+
+                                khui_alert_create_empty(&alert);
+
+                                LoadString(hResModule, IDS_CFG_RE_DMNUT,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText,
+                                               d->realms[r].realm);
+                                khui_alert_set_title(alert, buf);
+
+                                LoadString(hResModule, IDS_CFG_RE_DMNUM,
+                                           fmt, ARRAYLENGTH(fmt));
+                                StringCbPrintf(buf, sizeof(buf), fmt,
+                                               pdisp->item.pszText,
+                                               d->realms[r].realm);
+                                khui_alert_set_message(alert, buf);
+
+                                khui_alert_set_severity(alert, KHERR_INFO);
+                                khui_alert_show_modal(alert);
+
+                                khui_alert_release(alert);
+
+                                SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                                return TRUE;
+                            }
+
+                            if (m >= K5_MAX_DOMAIN_MAPPINGS) {
+                                SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+                                /* TODO: show a message box saying
+                                   there are too many domain mappings
+                                   already. */
+                                return TRUE;
+                            }
+
+                            StringCbCopy(d->realms[r].domain_maps[m].name,
+                                         sizeof(d->realms[0].domain_maps[0].name),
+                                         pdisp->item.pszText);
+                            d->realms[r].domain_maps[m].flags = K5_DMFLAG_NEW;
+                            d->realms[r].n_domain_maps++;
+
+                            k5_update_dmap_display(hw_dmp, d, d->c_realm);
+
+                            if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+                                d->flags |= K5_CDFLAG_MOD_REALMS;
+                                d->realms[r].flags |= K5_RDFLAG_MODIFED;
+                                k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+                            }
+                        }
+                        return TRUE;
+                    }
+                    break;
+
+                case LVN_KEYDOWN:
+                    {
+                        NMLVKEYDOWN * pnmk;
+
+                        pnmk = (NMLVKEYDOWN *) lParam;
+
+                        if (pnmk->wVKey == VK_DELETE) {
+                            k5_delete_dmap(hwnd, d);
+                            return TRUE;
+                        }
+                    }
+                    break;
+                }
+            } /* end of handling DMAP notifications */
+        }
+        break;
+
+    case WM_COMMAND:
+        switch(LOWORD(wParam)) {
+        case CMD_NEW_REALM:
+            {
+                ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_REALMS), 0);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_DEL_REALM:
+            {
+                k5_delete_realms(hwnd, d);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_NEW_SERVER:
+            {
+                ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_KDC), 0);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_DEL_SERVER:
+            {
+                k5_delete_servers(hwnd, d);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_MAKE_ADMIN:
+            {
+                HWND hw_kdc;
+                int idx;
+                khm_size r;
+                khm_size k;
+                BOOL modified = FALSE;
+
+                r = d->c_realm;
+
+                hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+
+                if (ListView_GetSelectedCount(hw_kdc) != 1)
+                    return TRUE;
+                
+                idx = -1;
+                while ((idx = ListView_GetNextItem(hw_kdc, idx,
+                                                   LVNI_SELECTED)) != -1) {
+                    LVITEM lvi;
+
+                    ZeroMemory(&lvi, sizeof(lvi));
+
+                    lvi.mask = LVIF_PARAM;
+                    lvi.iItem = idx;
+                    ListView_GetItem(hw_kdc, &lvi);
+
+                    k = lvi.lParam;
+
+                    if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) {
+                        d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin;
+                        d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN;
+                        modified = TRUE;
+
+                        break;
+                    }
+                }
+
+                if (modified) {
+                    if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+                        d->flags |= K5_CDFLAG_MOD_REALMS;
+                        d->realms[r].flags |= K5_RDFLAG_MODIFED;
+                        k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+                    }
+                }
+
+                k5_update_kdcs_display(hw_kdc, d, r);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_MAKE_MASTER:
+            {
+                HWND hw_kdc;
+                int idx;
+                khm_size r;
+                khm_size k;
+                BOOL modified = FALSE;
+
+                r = d->c_realm;
+
+                hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+
+                if (ListView_GetSelectedCount(hw_kdc) != 1)
+                    return TRUE;
+                
+                idx = -1;
+                while ((idx = ListView_GetNextItem(hw_kdc, idx,
+                                                   LVNI_SELECTED)) != -1) {
+                    LVITEM lvi;
+
+                    ZeroMemory(&lvi, sizeof(lvi));
+
+                    lvi.mask = LVIF_PARAM;
+                    lvi.iItem = idx;
+                    ListView_GetItem(hw_kdc, &lvi);
+
+                    k = lvi.lParam;
+
+                    if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) {
+                        if (d->realms[r].kdcs[k].master) {
+                            d->realms[r].kdcs[k].master = FALSE;
+                        } else {
+                            khm_size i;
+
+                            for (i=0; i < d->realms[r].n_kdcs; i++) {
+                                if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW) &&
+                                    (d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED))
+                                    continue;
+
+                                if (d->realms[r].kdcs[i].master) {
+                                    d->realms[r].kdcs[i].master = FALSE;
+                                    d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER;
+                                }
+                            }
+
+                            d->realms[r].kdcs[k].master = TRUE;
+                        }
+                        d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+                        modified = TRUE;
+
+                        break;
+                    }
+                }
+
+                if (modified) {
+                    if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+                        d->flags |= K5_CDFLAG_MOD_REALMS;
+                        d->realms[r].flags |= K5_RDFLAG_MODIFED;
+                        k5_update_realms_display(hwnd, d);
+                    }
+                }
+
+                k5_update_kdcs_display(hw_kdc, d, r);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_NEW_DMAP:
+            {
+                ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_DMAP), 0);
+
+                return TRUE;
+            }
+            break;
+
+        case CMD_DEL_DMAP:
+            {
+                k5_delete_dmap(hwnd, d);
+
+                return TRUE;
+            }
+            break;
+        }
+        break;
+
+    case WM_DESTROY:
+        if (d->hm_realms_ctx)
+            DestroyMenu(d->hm_realms_ctx);
+        if (d->hm_kdc_ctx)
+            DestroyMenu(d->hm_kdc_ctx);
+        if (d->hm_dmap_ctx)
+            DestroyMenu(d->hm_dmap_ctx);
+
+        d->hm_realms_ctx = NULL;
+        d->hm_kdc_ctx = NULL;
+        d->hm_dmap_ctx = NULL;
+        break;
+
+    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. */
+        if (HIWORD(wParam) == WMCFG_APPLY) {
+            k5_purge_config_data(d, TRUE, TRUE, TRUE);
+            k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+            if (d->c_realm != -1) {
+                k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), d, d->c_realm);
+                k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), d, d->c_realm);
+            } else {
+                k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
+                k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
+            }
+        }
+        break;
+    }
+    return FALSE;
+}
+
+void
+k5_register_config_panels(void) {
+    khui_config_node node;
+    khui_config_node_reg reg;
+    wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+    wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
+
+    ZeroMemory(&reg, sizeof(reg));
+
+    LoadString(hResModule, IDS_K5CFG_SHORT_DESC,
+               wshort, ARRAYLENGTH(wshort));
+    LoadString(hResModule, IDS_K5CFG_LONG_DESC,
+               wlong, ARRAYLENGTH(wlong));
+
+    reg.name = L"Kerberos5";
+    reg.short_desc = wshort;
+    reg.long_desc = wlong;
+    reg.h_module = hResModule;
+    reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
+    reg.dlg_proc = k5_config_dlgproc;
+    reg.flags = 0;
+
+    khui_cfg_register(NULL, &reg);
+
+    if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {
+        node = NULL;
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+    }
+
+    ZeroMemory(&reg, sizeof(reg));
+
+    LoadString(hResModule, IDS_K5RLM_SHORT_DESC,
+               wshort, ARRAYLENGTH(wshort));
+    LoadString(hResModule, IDS_K5RLM_LONG_DESC,
+               wlong, ARRAYLENGTH(wlong));
+
+    reg.name = L"KerberosRealms";
+    reg.short_desc = wshort;
+    reg.long_desc = wlong;
+    reg.h_module = hResModule;
+    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS);
+    reg.dlg_proc = k5_realms_dlgproc;
+    reg.flags = 0;
+
+    khui_cfg_register(node, &reg);
+
+    ZeroMemory(&reg, sizeof(reg));
+
+    LoadString(hResModule, IDS_K5CCC_SHORT_DESC,
+               wshort, ARRAYLENGTH(wshort));
+    LoadString(hResModule, IDS_K5CCC_LONG_DESC,
+               wlong, ARRAYLENGTH(wlong));
+
+    reg.name = L"KerberosCCaches";
+    reg.short_desc = wshort;
+    reg.long_desc = wlong;
+    reg.h_module = hResModule;
+    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_CACHES);
+    reg.dlg_proc = k5_ccconfig_dlgproc;
+    reg.flags = 0;
+
+    khui_cfg_register(node, &reg);
+
+    khui_cfg_release(node);
+
+    if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {
+        node = NULL;
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+    }
+
+    ZeroMemory(&reg, sizeof(reg));
+
+    LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC,
+               wshort, ARRAYLENGTH(wshort));
+    LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC,
+               wlong, ARRAYLENGTH(wlong));
+
+    reg.name = L"KerberosIdentities";
+    reg.short_desc = wshort;
+    reg.long_desc = wlong;
+    reg.h_module = hResModule;
+    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
+    reg.dlg_proc = k5_ids_tab_dlgproc;
+    reg.flags = KHUI_CNFLAG_SUBPANEL;
+
+    khui_cfg_register(node, &reg);
+
+    ZeroMemory(&reg, sizeof(reg));
+
+    LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC,
+               wshort, ARRAYLENGTH(wshort));
+    LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC,
+               wlong, ARRAYLENGTH(wlong));
+
+    reg.name = L"KerberosIdentitiesPlural";
+    reg.short_desc = wshort;
+    reg.long_desc = wlong;
+    reg.h_module = hResModule;
+    reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
+    reg.dlg_proc = k5_id_tab_dlgproc;
+    reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
+
+    khui_cfg_register(node, &reg);
+
+    khui_cfg_release(node);
+}
+
+void
+k5_unregister_config_panels(void) {
+    khui_config_node node_main;
+    khui_config_node node_realms;
+    khui_config_node node_ids;
+    khui_config_node node_tab;
+    khui_config_node node_ccaches;
+
+    if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) {
+        node_main = NULL;
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+    }
+
+    if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms", 
+                                    &node_realms))) {
+        khui_cfg_remove(node_realms);
+        khui_cfg_release(node_realms);
+    } else {
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+    }
+
+    if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosCCaches",
+                                    &node_ccaches))) {
+        khui_cfg_remove(node_ccaches);
+        khui_cfg_release(node_ccaches);
+    }
+#ifdef DEBUG
+    else
+        assert(FALSE);
+#endif
+
+    if (node_main) {
+        khui_cfg_remove(node_main);
+        khui_cfg_release(node_main);
+    }
+
+    if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) {
+        node_ids = NULL;
+#ifdef DEBUG
+        assert(FALSE);
+#endif
+    }
+
+    if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) {
+        khui_cfg_remove(node_tab);
+        khui_cfg_release(node_tab);
+    }
+    if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) {
+        khui_cfg_remove(node_tab);
+        khui_cfg_release(node_tab);
+    }
+
+    if (node_ids)
+        khui_cfg_release(node_ids);
+}
index a4e549d3d245085a54696dc1d3a466f91f3e835c..ccc38941a6b77ef9a08f70b79440d9a1cb701203 100644 (file)
@@ -45,6 +45,13 @@ typedef struct tag_k5_id_dlg_data {
 \r
     wchar_t ccache[KRB5_MAXCCH_CCNAME];\r
 \r
+    khm_boolean renewable;\r
+    khm_boolean forwardable;\r
+    khm_boolean proxiable;\r
+    khm_boolean addressless;\r
+\r
+    DWORD public_ip;\r
+\r
     time_t life;\r
     time_t renew_life;\r
 } k5_id_dlg_data;\r
@@ -94,6 +101,36 @@ k5_id_read_params(k5_id_dlg_data * d) {
     else\r
         d->renew_life = 604800;\r
 \r
+    rv = khc_read_int32(csp_ident, L"Renewable", &t);\r
+    if (KHM_SUCCEEDED(rv))\r
+        d->renewable = !!t;\r
+    else\r
+        d->renewable = TRUE;\r
+\r
+    rv = khc_read_int32(csp_ident, L"Forwardable", &t);\r
+    if (KHM_SUCCEEDED(rv))\r
+        d->forwardable = !!t;\r
+    else\r
+        d->forwardable = FALSE;\r
+\r
+    rv = khc_read_int32(csp_ident, L"Proxiable", &t);\r
+    if (KHM_SUCCEEDED(rv))\r
+        d->proxiable = !!t;\r
+    else\r
+        d->proxiable = FALSE;\r
+\r
+    rv = khc_read_int32(csp_ident, L"Addressless", &t);\r
+    if (KHM_SUCCEEDED(rv))\r
+        d->addressless = !!t;\r
+    else\r
+        d->addressless = TRUE;\r
+\r
+    rv = khc_read_int32(csp_ident, L"PublicIP", &t);\r
+    if (KHM_SUCCEEDED(rv))\r
+        d->public_ip = (khm_ui_4) t;\r
+    else\r
+        d->public_ip = 0;\r
+\r
     cb = sizeof(d->ccache);\r
     rv = khc_read_string(csp_ident, L"DefaultCCName", d->ccache, &cb);\r
     if (KHM_FAILED(rv) || cb <= sizeof(wchar_t)) {\r
@@ -120,13 +157,30 @@ k5_id_read_params(k5_id_dlg_data * d) {
 static khm_boolean\r
 k5_id_is_mod(HWND hw, k5_id_dlg_data * d) {\r
     wchar_t ccache[KRB5_MAXCCH_CCNAME];\r
+    DWORD dwaddress = 0;\r
 \r
     GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));\r
 \r
+    SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,\r
+                       0, (LPARAM) &dwaddress);\r
+\r
     if (wcsicmp(ccache, d->ccache) ||\r
+\r
         d->tc_renew.current != d->renew_life ||\r
-        d->tc_life.current != d->life)\r
+\r
+        d->tc_life.current != d->life ||\r
+\r
+        (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable ||\r
+\r
+        (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable ||\r
+\r
+        (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED)\r
+        != d->addressless ||\r
+\r
+        dwaddress != d->public_ip)\r
+\r
         return TRUE;\r
+\r
     return FALSE;\r
 }\r
 \r
@@ -147,6 +201,8 @@ k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
     wchar_t ccache[KRB5_MAXCCH_CCNAME];\r
     khm_size cb;\r
     khm_int32 rv;\r
+    khm_boolean b;\r
+    DWORD dwaddress = 0;\r
 \r
     if (!k5_id_is_mod(hw, d))\r
         return;\r
@@ -174,6 +230,32 @@ k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
         khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life);\r
     }\r
 \r
+    b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED);\r
+    if (b != d->renewable) {\r
+        d->renewable = b;\r
+        khc_write_int32(csp_ident, L"Renewable", (khm_int32) b);\r
+    }\r
+\r
+    b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED);\r
+    if (b != d->forwardable) {\r
+        d->forwardable = b;\r
+        khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b);\r
+    }\r
+\r
+    b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED);\r
+    if (b != d->addressless) {\r
+        d->addressless = b;\r
+        khc_write_int32(csp_ident, L"Addressless", (khm_int32) b);\r
+    }\r
+\r
+    SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,\r
+                       0, (LPARAM) &dwaddress);\r
+\r
+    if (dwaddress != d->public_ip) {\r
+        d->public_ip = dwaddress;\r
+        khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress);\r
+    }\r
+\r
     GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));\r
 \r
     if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) &&\r
@@ -225,6 +307,19 @@ k5_id_tab_dlgproc(HWND hwnd,
         khui_tracker_refresh(&d->tc_renew);\r
 \r
         SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache);\r
+\r
+        CheckDlgButton(hwnd, IDC_CFG_RENEW,\r
+                       (d->renewable? BST_CHECKED: BST_UNCHECKED));\r
+\r
+        CheckDlgButton(hwnd, IDC_CFG_FORWARD,\r
+                       (d->forwardable? BST_CHECKED: BST_UNCHECKED));\r
+\r
+        CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS,\r
+                       (d->addressless? BST_CHECKED: BST_UNCHECKED));\r
+\r
+        SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP,\r
+                           IPM_SETADDRESS,\r
+                           0, (LPARAM) d->public_ip);\r
         break;\r
 \r
     case WM_COMMAND:\r
index 5c076951a62e9af901811de89a2e3fc5a0abba7c..af2d997c87075cef4731a82bc5d585fb06ffd988 100644 (file)
@@ -203,6 +203,8 @@ int com_addr(void)
 #define ENCTYPE_LOCAL_RC4_MD4    0xFFFFFF80\r
 #endif\r
 \r
+#define MAX_ADDRS 256\r
+\r
 static long get_tickets_from_cache(krb5_context ctx, \r
                                    krb5_ccache cache)\r
 {\r
@@ -223,7 +225,6 @@ static long get_tickets_from_cache(krb5_context ctx,
     FILETIME        ft, eft;\r
     khm_int32       ti;\r
 \r
-\r
 #ifdef KRB5_TC_NOTICKET\r
     flags = KRB5_TC_NOTICKET;\r
 #else\r
@@ -442,30 +443,33 @@ static long get_tickets_from_cache(krb5_context ctx,
         kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name, \r
                            KCDB_CBSIZE_AUTO);\r
 \r
-        /*TODO: going here */\r
-#if 0\r
         if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {\r
-            int n = 0;\r
-            while ( KRBv5Credentials.addresses[n] )\r
-                n++;\r
-            list->addrList = PCALLOC(1, n * sizeof(char *));\r
-            if (!list->addrList) {\r
-                MessageBox(NULL, "Memory Error", "Error", MB_OK);\r
-                return ENOMEM;            \r
-            }\r
-            list->addrCount = n;\r
-            for ( n=0; n<list->addrCount; n++ ) {\r
-                wsprintf(Buffer, "Address: %s", one_addr(KRBv5Credentials.addresses[n]));\r
-                list->addrList[n] = (char*) PCALLOC(1, strlen(Buffer)+1);\r
-                if (!list->addrList[n])\r
-                {\r
-                    MessageBox(NULL, "Memory Error", "Error", MB_OK);\r
-                    return ENOMEM;            \r
-                }       \r
-                strcpy(list->addrList[n], Buffer);\r
-            }   \r
+           khm_int32 buffer[1024];\r
+           void * bufp;\r
+           khm_size cb;\r
+           khm_int32 rv;\r
+\r
+           bufp = (void *) buffer;\r
+           cb = sizeof(buffer);\r
+\r
+           rv = serialize_krb5_addresses(KRBv5Credentials.addresses,\r
+                                         bufp,\r
+                                         &cb);\r
+           if (rv == KHM_ERROR_TOO_LONG) {\r
+               bufp = PMALLOC(cb);\r
+               rv = serialize_krb5_addresses(KRBv5Credentials.addresses,\r
+                                             bufp,\r
+                                             &cb);\r
+           }\r
+\r
+           if (KHM_SUCCEEDED(rv)) {\r
+               kcdb_cred_set_attr(cred, attr_id_addr_list,\r
+                                  bufp, cb);\r
+           }\r
+\r
+           if (bufp != (void *) buffer)\r
+               PFREE(bufp);\r
         }\r
-#endif\r
 \r
         if(cred_flags & KCDB_CRED_FLAG_INITIAL) {\r
             FILETIME ft_issue_new;\r
@@ -597,10 +601,16 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
     ctx = (*krbv5Context);\r
 \r
     for(i=0; pNCi[i]; i++) {\r
+        char ccname[KRB5_MAXCCH_CCNAME];\r
+\r
         if (pNCi[i]->vers != CC_CRED_V5)\r
             continue;\r
 \r
-        code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);\r
+        if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s",\r
+                                    pNCi[i]->name)))\r
+            continue;\r
+\r
+        code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);\r
 \r
         if (code)\r
             continue;\r
@@ -668,7 +678,49 @@ _exit:
 }\r
 \r
 int\r
-khm_krb5_renew(khm_handle identity)\r
+khm_krb5_renew_cred(khm_handle cred)\r
+{\r
+    khm_handle          identity = NULL;\r
+    krb5_error_code     code = 0;\r
+    krb5_context        ctx = 0;\r
+    krb5_ccache         cc = 0;\r
+\r
+    if (cred == NULL) {\r
+#ifdef DEBUG\r
+       assert(FALSE);\r
+#endif\r
+       goto _cleanup;\r
+    }\r
+\r
+    if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) {\r
+#ifdef DEBUG\r
+       assert(FALSE);\r
+#endif\r
+       goto _cleanup;\r
+    }\r
+\r
+    code = khm_krb5_initialize(identity, &ctx, &cc);\r
+    if (code)\r
+       goto _cleanup;\r
+\r
+    /* TODO: going here */\r
+\r
+ _cleanup:\r
+\r
+    if (identity)\r
+       kcdb_identity_release(identity);\r
+\r
+    if (cc && ctx)\r
+       pkrb5_cc_close(ctx, cc);\r
+\r
+    if (ctx)\r
+       pkrb5_free_context(ctx);\r
+\r
+    return code;\r
+}\r
+\r
+int\r
+khm_krb5_renew_ident(khm_handle identity)\r
 {\r
     krb5_error_code     code = 0;\r
     krb5_context        ctx = 0;\r
@@ -771,24 +823,67 @@ khm_krb5_kinit(krb5_context       alt_ctx,
     if (!pkrb5_init_context)\r
         return 0;\r
 \r
+    _reportf(L"In khm_krb5_kinit");\r
+\r
     pkrb5_get_init_creds_opt_init(&options);\r
     memset(&my_creds, 0, sizeof(my_creds));\r
 \r
-    if (alt_ctx)\r
-    {\r
+    if (alt_ctx) {\r
         ctx = alt_ctx;\r
-    }\r
-    else\r
-    {\r
+    } else {\r
         code = pkrb5_init_context(&ctx);\r
-        if (code) goto cleanup;\r
+        if (code)\r
+            goto cleanup;\r
     }\r
 \r
-//    code = pkrb5_cc_default(ctx, &cc);\r
-    if (ccache)\r
+    if (ccache) {\r
+        _reportf(L"Using supplied ccache name %S", ccache);\r
         code = pkrb5_cc_resolve(ctx, ccache, &cc);\r
-    else\r
-        code = pkrb5_cc_resolve(ctx, principal_name, &cc);\r
+    } else {\r
+       khm_handle identity = NULL;\r
+       khm_handle csp_ident = NULL;\r
+       khm_handle csp_k5 = NULL;\r
+       wchar_t idname[KCDB_IDENT_MAXCCH_NAME];\r
+       wchar_t wccname[MAX_PATH];\r
+       char ccname[MAX_PATH];\r
+       char * pccname = principal_name;\r
+       khm_size cb;\r
+\r
+       idname[0] = L'\0';\r
+       AnsiStrToUnicode(idname, sizeof(idname), principal_name);\r
+\r
+       cb = sizeof(wccname);\r
+\r
+       if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) &&\r
+\r
+           KHM_SUCCEEDED(kcdb_identity_get_config(identity, 0, &csp_ident)) &&\r
+\r
+           KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0,\r
+                                        &csp_k5)) &&\r
+\r
+           KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",\r
+                                         wccname, &cb)) &&\r
+\r
+           cb > sizeof(wchar_t)) {\r
+\r
+            _reportf(L"Using DefaultCCName [%s] from identity", wccname);\r
+\r
+           UnicodeStrToAnsi(ccname, sizeof(ccname), wccname);\r
+           pccname = ccname;\r
+       }\r
+\r
+       if (csp_k5)\r
+           khc_close_space(csp_k5);\r
+       if (csp_ident)\r
+           khc_close_space(csp_ident);\r
+       if (identity)\r
+           kcdb_identity_release(identity);\r
+\r
+        code = pkrb5_cc_resolve(ctx, pccname, &cc);\r
+    }\r
+\r
+    _reportf(L"krb5_cc_resolve returns code %d", code);\r
+\r
     if (code) goto cleanup;\r
 \r
     code = pkrb5_parse_name(ctx, principal_name, &me);\r
@@ -803,55 +898,57 @@ khm_krb5_kinit(krb5_context       alt_ctx,
 \r
     if (lifetime)\r
         pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);\r
+\r
     pkrb5_get_init_creds_opt_set_forwardable(&options,\r
         forwardable ? 1 : 0);\r
     pkrb5_get_init_creds_opt_set_proxiable(&options,\r
         proxiable ? 1 : 0);\r
     pkrb5_get_init_creds_opt_set_renew_life(&options,\r
         renew_life);\r
+\r
     if (addressless)\r
         pkrb5_get_init_creds_opt_set_address_list(&options,NULL);\r
     else {\r
-        if (publicIP)\r
-        {\r
-            // we are going to add the public IP address specified by the user\r
-            // to the list provided by the operating system\r
-            krb5_address ** local_addrs=NULL;\r
-            DWORD           netIPAddr;\r
-\r
-            pkrb5_os_localaddr(ctx, &local_addrs);\r
-            while ( local_addrs[i++] );\r
-            addr_count = i + 1;\r
-\r
-            addrs = (krb5_address **) PMALLOC((addr_count+1) * sizeof(krb5_address *));\r
-            if ( !addrs ) {\r
-                pkrb5_free_addresses(ctx, local_addrs);\r
-                assert(0);\r
-            }\r
-            memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));\r
-            i = 0;\r
-            while ( local_addrs[i] ) {\r
-                addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));\r
-                if (addrs[i] == NULL) {\r
-                    pkrb5_free_addresses(ctx, local_addrs);\r
-                    assert(0);\r
-                }\r
+       krb5_address ** local_addrs=NULL;\r
+       DWORD           netIPAddr;\r
+\r
+       pkrb5_os_localaddr(ctx, &local_addrs);\r
+       i = 0;\r
+       while ( local_addrs[i++] );\r
+       addr_count = i + 1;\r
+\r
+       addrs = (krb5_address **) PMALLOC((addr_count+1) * sizeof(krb5_address *));\r
+       if ( !addrs ) {\r
+           pkrb5_free_addresses(ctx, local_addrs);\r
+           assert(0);\r
+       }\r
+       memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));\r
+       i = 0;\r
+       while ( local_addrs[i] ) {\r
+           addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));\r
+           if (addrs[i] == NULL) {\r
+               pkrb5_free_addresses(ctx, local_addrs);\r
+               assert(0);\r
+           }\r
 \r
-                addrs[i]->magic = local_addrs[i]->magic;\r
-                addrs[i]->addrtype = local_addrs[i]->addrtype;\r
-                addrs[i]->length = local_addrs[i]->length;\r
-                addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);\r
-                if (!addrs[i]->contents) {\r
-                    pkrb5_free_addresses(ctx, local_addrs);\r
-                    assert(0);\r
-                }\r
+           addrs[i]->magic = local_addrs[i]->magic;\r
+           addrs[i]->addrtype = local_addrs[i]->addrtype;\r
+           addrs[i]->length = local_addrs[i]->length;\r
+           addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length);\r
+           if (!addrs[i]->contents) {\r
+               pkrb5_free_addresses(ctx, local_addrs);\r
+               assert(0);\r
+           }\r
 \r
-                memcpy(addrs[i]->contents,local_addrs[i]->contents,\r
-                    local_addrs[i]->length);        /* safe */\r
-                i++;\r
-            }\r
-            pkrb5_free_addresses(ctx, local_addrs);\r
+           memcpy(addrs[i]->contents,local_addrs[i]->contents,\r
+                  local_addrs[i]->length);        /* safe */\r
+           i++;\r
+       }\r
+       pkrb5_free_addresses(ctx, local_addrs);\r
 \r
+        if (publicIP) {\r
+            // we are going to add the public IP address specified by the user\r
+            // to the list provided by the operating system\r
             addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address));\r
             if (addrs[i] == NULL)\r
                 assert(0);\r
@@ -865,27 +962,31 @@ khm_krb5_kinit(krb5_context       alt_ctx,
 \r
             netIPAddr = htonl(publicIP);\r
             memcpy(addrs[i]->contents,&netIPAddr,4);\r
-\r
-            pkrb5_get_init_creds_opt_set_address_list(&options,addrs);\r
-\r
         }\r
+\r
+       pkrb5_get_init_creds_opt_set_address_list(&options,addrs);\r
     }\r
 \r
-    code = pkrb5_get_init_creds_password(ctx,\r
-        &my_creds,\r
-        me,\r
-        password, // password\r
-        prompter, // prompter\r
-        p_data, // prompter data\r
-        0, // start time\r
-        0, // service name\r
-        &options);\r
+    code =\r
+        pkrb5_get_init_creds_password(ctx,\r
+                                      &my_creds,\r
+                                      me,\r
+                                      password, // password\r
+                                      prompter, // prompter\r
+                                      p_data, // prompter data\r
+                                      0, // start time\r
+                                      0, // service name\r
+                                      &options);\r
+    _reportf(L"krb5_get_init_creds_password returns code %d", code);\r
+\r
     if (code) goto cleanup;\r
 \r
     code = pkrb5_cc_initialize(ctx, cc, me);\r
+    _reportf(L"krb5_cc_initialize returns code %d", code);\r
     if (code) goto cleanup;\r
 \r
     code = pkrb5_cc_store_cred(ctx, cc, &my_creds);\r
+    _reportf(L"krb5_cc_store_cred returns code %d", code);\r
     if (code) goto cleanup;\r
 \r
 cleanup:\r
@@ -1157,7 +1258,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
     kcdb_credset_get_size(d_cs, &s);\r
 \r
     if (s == 0) {\r
-        /* nothing to do */\r
+        _reportf(L"No tickets to delete");\r
+\r
         kcdb_credset_delete(d_cs);\r
         return 0;\r
     }\r
@@ -1215,6 +1317,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
             char a_ccname[KRB5_MAXCCH_CCNAME];\r
             krb5_ccache cc = NULL;\r
 \r
+            _reportf(L"Destroying ccache [%s]", ccname);\r
+\r
             UnicodeStrToAnsi(a_ccname,\r
                              sizeof(a_ccname),\r
                              ccname);\r
@@ -1228,7 +1332,7 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
             code = pkrb5_cc_destroy(ctx, cc);\r
 \r
             if (code) {\r
-                /*TODO: report error */\r
+                _reportf(L"krb5_cc_destroy returns code %d", code);\r
             }\r
 \r
         _delete_this_set:\r
@@ -1280,6 +1384,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
                                           &cb)))\r
             goto _done_with_this_cred;\r
 \r
+        _reportf(L"Looking at ccache [%s]", ccname);\r
+\r
         UnicodeStrToAnsi(a_ccname,\r
                          sizeof(a_ccname),\r
                          ccname);\r
@@ -1315,6 +1421,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
                                           &cb)))\r
             goto _do_next_cred;\r
 \r
+        _reportf(L"Attempting to delete ticket %s", srvname);\r
+\r
         UnicodeStrToAnsi(a_srvname, sizeof(a_srvname), srvname);\r
 \r
         ZeroMemory(&in_cred, sizeof(in_cred));\r
@@ -1740,7 +1848,8 @@ readstring(FILE * file, char * buf, int len)
     \return The string with the list of realms or NULL if the\r
     operation fails.\r
 */\r
-wchar_t * khm_krb5_get_realm_list(void) \r
+wchar_t * \r
+khm_krb5_get_realm_list(void) \r
 {\r
     wchar_t * rlist = NULL;\r
 \r
@@ -1865,7 +1974,8 @@ wchar_t * khm_krb5_get_realm_list(void)
 \r
     Returns NULL if the operation fails.\r
 */\r
-wchar_t * khm_krb5_get_default_realm(void)\r
+wchar_t * \r
+khm_krb5_get_default_realm(void)\r
 {\r
     wchar_t * realm;\r
     size_t cch;\r
@@ -1914,7 +2024,8 @@ khm_krb5_set_default_realm(wchar_t * realm) {
     return rv;\r
 }\r
 \r
-wchar_t * khm_get_realm_from_princ(wchar_t * princ) {\r
+wchar_t * \r
+khm_get_realm_from_princ(wchar_t * princ) {\r
     wchar_t * t;\r
 \r
     if(!princ)\r
index 6c2c3eb6b935dcc67288e017e4e156ae759d10ea..d699508367281979843f8aa444a4f0b1c74f74ef 100644 (file)
@@ -84,8 +84,11 @@ khm_krb5_destroy_identity(khm_handle identity);
 long\r
 khm_convert524(krb5_context ctx);\r
 \r
+int\r
+khm_krb5_renew_cred(khm_handle cred);\r
+\r
 int \r
-khm_krb5_renew(khm_handle identity);\r
+khm_krb5_renew_ident(khm_handle identity);\r
 \r
 wchar_t * \r
 khm_krb5_get_default_realm(void);\r
index 2ad904b43a58f7b86e946274263dd19f692ab68f..f12e6a9b97f96f80ac0f7533b5737f45eb8bb1e4 100644 (file)
@@ -74,6 +74,7 @@ set_identity_from_ui(khui_new_creds * nc,
     khm_size cch_left;\r
     khm_handle ident;\r
     LRESULT idx = CB_ERR;\r
+    khm_int32 rv = KHM_ERROR_SUCCESS;\r
 \r
     cch = GetWindowTextLength(d->hw_username);\r
 \r
@@ -91,23 +92,34 @@ set_identity_from_ui(khui_new_creds * nc,
        be exact.  For caveats see MSDN for GetWindowTextLength. */\r
     StringCchLength(un, KCDB_IDENT_MAXCCH_NAME, &cch);\r
 \r
+    if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) {\r
+        /* has to allow space for the '@' and at least a single\r
+           character realm, and the NULL terminator. */\r
+        rv = KHM_ERROR_TOO_LONG;\r
+        goto _set_null_ident;\r
+    }\r
+\r
     realm = un + cch;   /* now points at terminating NULL */\r
     cch_left = KCDB_IDENT_MAXCCH_NAME - cch;\r
 \r
     *realm++ = L'@';\r
+    *realm = L'\0';\r
     cch_left--;\r
 \r
     cch = GetWindowTextLength(d->hw_realm);\r
-    if (cch == 0 || cch >= cch_left)\r
+    if (cch == 0 || cch >= cch_left) {\r
+        rv = KHM_ERROR_INVALID_NAME;\r
         goto _set_null_ident;\r
+    }\r
 \r
     GetWindowText(d->hw_realm, realm, (int) cch_left);\r
 \r
  _set_ident:\r
-    if (KHM_FAILED(kcdb_identity_create(un,\r
-                                        KCDB_IDENT_FLAG_CREATE,\r
-                                        &ident)))\r
+    if (KHM_FAILED(rv = kcdb_identity_create(un,\r
+                                             KCDB_IDENT_FLAG_CREATE,\r
+                                             &ident))) {\r
         goto _set_null_ident;\r
+    }\r
 \r
     khui_cw_set_primary_id(nc, ident);\r
 \r
@@ -115,7 +127,37 @@ set_identity_from_ui(khui_new_creds * nc,
     return;\r
 \r
  _set_null_ident:\r
-    khui_cw_set_primary_id(nc, NULL);\r
+    {\r
+        khui_new_creds_by_type * nct = NULL;\r
+        wchar_t cmsg[256];\r
+\r
+        khui_cw_find_type(nc, credtype_id_krb5, &nct);\r
+        if (nct && nct->hwnd_panel) {\r
+\r
+            switch(rv) {\r
+            case KHM_ERROR_TOO_LONG:\r
+                LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG,\r
+                           cmsg, ARRAYLENGTH(cmsg));\r
+                break;\r
+\r
+            case KHM_ERROR_INVALID_NAME:\r
+                LoadString(hResModule, IDS_NCERR_IDENT_INVALID,\r
+                           cmsg, ARRAYLENGTH(cmsg));\r
+                break;\r
+\r
+            default:\r
+                LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN,\r
+                           cmsg, ARRAYLENGTH(cmsg));\r
+            }\r
+\r
+            SendMessage(nct->hwnd_panel,\r
+                        KHUI_WM_NC_NOTIFY,\r
+                        MAKEWPARAM(0, K5_SET_CRED_MSG),\r
+                        (LPARAM) cmsg);\r
+        }\r
+\r
+        khui_cw_set_primary_id(nc, NULL);\r
+    }\r
     return;\r
 }\r
 \r
@@ -957,9 +999,9 @@ k5_ident_update_apply_proc(khm_handle cred,
     khm_handle ident = NULL;\r
     khm_int32 t;\r
     khm_int32 flags;\r
-    __int64 t_expire;\r
-       __int64 t_cexpire;\r
-    __int64 t_rexpire;\r
+    FILETIME t_expire;\r
+    FILETIME t_cexpire;\r
+    FILETIME t_rexpire;\r
     khm_size cb;\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
 \r
@@ -980,24 +1022,26 @@ k5_ident_update_apply_proc(khm_handle cred,
                                              KCDB_ATTR_EXPIRE,\r
                                              NULL,\r
                                              &t_cexpire,\r
-                                             &cb))) {                                                                           \r
-                t_expire = 0;\r
-                cb = sizeof(t_expire);\r
-                if (KHM_FAILED(kcdb_identity_get_attr(tident,\r
-                                                      KCDB_ATTR_EXPIRE,\r
-                                                      NULL,\r
-                                                      &t_expire,\r
-                                                      &cb)) ||\r
-                    (t_cexpire > t_expire))\r
-                    kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,\r
-                                           &t_cexpire, sizeof(t_cexpire));\r
-        } else {\r
-            kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE, NULL, 0);\r
+                                             &cb))) {\r
+            cb = sizeof(t_expire);\r
+            if (KHM_FAILED(kcdb_identity_get_attr(tident,\r
+                                                  KCDB_ATTR_EXPIRE,\r
+                                                  NULL,\r
+                                                  &t_expire,\r
+                                                  &cb)) ||\r
+                CompareFileTime(&t_cexpire, &t_expire) > 0) {\r
+                goto update_identity;\r
+            }\r
         }\r
-    } else {\r
-        goto _cleanup;\r
     }\r
 \r
+    goto _cleanup;\r
+\r
+ update_identity:\r
+\r
+    kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,\r
+                           &t_cexpire, sizeof(t_cexpire));\r
+\r
     cb = sizeof(ccname);\r
     if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION,\r
                                          NULL,\r
index d324857feb56fd0addb9f586ce21f74415cc3e1a..ee85355a0bf254b9fa9cd2162e707fd1df48fb58 100644 (file)
@@ -94,10 +94,12 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
     ZeroMemory(&pi, sizeof(pi));\r
     pi.name = KRB5_PLUGIN_NAME;\r
     pi.type = KHM_PITYPE_CRED;\r
-    pi.icon = NULL; /*TODO: Assign icon */\r
+    pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),\r
+                        IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);\r
     pi.flags = 0;\r
     pi.msg_proc = k5_msg_callback;\r
     pi.description = buf;\r
+    pi.dependencies = NULL;\r
     LoadString(hResModule, IDS_PLUGIN_DESC,\r
                buf, ARRAYLENGTH(buf));\r
     kmm_provide_plugin(h_module, &pi);\r
@@ -105,7 +107,8 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
     ZeroMemory(&pi, sizeof(pi));\r
     pi.name = KRB5_IDENTPRO_NAME;\r
     pi.type = KHM_PITYPE_IDENT;\r
-    pi.icon = NULL;             /* ignored */\r
+    pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),\r
+                        IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);\r
     pi.flags = 0;\r
     pi.msg_proc = k5_ident_callback;\r
     pi.description = buf;\r
@@ -157,7 +160,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         type.cb_min = 0;\r
         type.cb_max = 0;\r
         type.isValid = tdata->isValid;\r
-        type.comp = tdata->comp;\r
+        type.comp = addr_list_comp;\r
         type.dup = tdata->dup;\r
         type.toString = addr_list_toString;\r
 \r
@@ -206,7 +209,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attrib.name = ATTRNAME_KEY_ENCTYPE;\r
         attrib.id = KCDB_ATTR_INVALID;\r
         attrib.type = type_id_enctype;\r
-        attrib.flags = 0;\r
+        attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;\r
         LoadString(hResModule, IDS_KEY_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));\r
         LoadString(hResModule, IDS_KEY_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));\r
         attrib.short_desc = sbuf;\r
@@ -232,7 +235,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attrib.name = ATTRNAME_TKT_ENCTYPE;\r
         attrib.id = KCDB_ATTR_INVALID;\r
         attrib.type = type_id_enctype;\r
-        attrib.flags = 0;\r
+        attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;\r
         LoadString(hResModule, IDS_TKT_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));\r
         LoadString(hResModule, IDS_TKT_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));\r
         attrib.short_desc = sbuf;\r
@@ -258,7 +261,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attrib.name = ATTRNAME_ADDR_LIST;\r
         attrib.id = KCDB_ATTR_INVALID;\r
         attrib.type = type_id_addr_list;\r
-        attrib.flags = 0;\r
+        attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;\r
         LoadString(hResModule, IDS_ADDR_LIST_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));\r
         LoadString(hResModule, IDS_ADDR_LIST_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));\r
         attrib.short_desc = sbuf;\r
@@ -284,7 +287,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attrib.name = ATTRNAME_KRB5_FLAGS;\r
         attrib.id = KCDB_ATTR_INVALID;\r
         attrib.type = type_id_krb5_flags;\r
-        attrib.flags = 0;\r
+        attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;\r
         LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));\r
         attrib.short_desc = sbuf;\r
         attrib.long_desc = NULL;\r
@@ -309,7 +312,9 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attrib.name = ATTRNAME_KRB5_CCNAME;\r
         attrib.id = KCDB_ATTR_INVALID;\r
         attrib.type = KCDB_TYPE_STRING;\r
-        attrib.flags = KCDB_ATTR_FLAG_PROPERTY;\r
+        attrib.flags =\r
+         KCDB_ATTR_FLAG_PROPERTY |\r
+         KCDB_ATTR_FLAG_TRANSIENT;\r
         LoadString(hResModule, IDS_KRB5_CCNAME_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));\r
         LoadString(hResModule, IDS_KRB5_CCNAME_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));\r
         attrib.short_desc = sbuf;\r
index e6bf6479de4ab98e7f69fc4b1ea81cf82e9ea1dc..c896537794c830a1f06d22e781e613d929d8b2f3 100644 (file)
@@ -30,6 +30,8 @@
 #include<strsafe.h>\r
 #include<krb5.h>\r
 \r
+#include<commctrl.h>\r
+\r
 #include<assert.h>\r
 \r
 extern LPVOID k5_main_fiber;\r
@@ -41,8 +43,10 @@ typedef struct k5_dlg_data_t {
     khui_tracker tc_lifetime;\r
     khui_tracker tc_renew;\r
 \r
-    BOOL dirty;\r
-\r
+    BOOL dirty;                 /* is the data in sync with the\r
+                                   configuration store? */\r
+    BOOL sync;                  /* is the data in sync with the kinit\r
+                                   request? */\r
     DWORD   renewable;\r
     DWORD   forwardable;\r
     DWORD   proxiable;\r
@@ -99,9 +103,9 @@ k5_handle_wm_destroy(HWND hwnd,
 \r
     d = (k5_dlg_data *) (LONG_PTR)\r
         GetWindowLongPtr(hwnd, DWLP_USER);\r
-#ifdef DEBUG\r
-    assert(d);\r
-#endif\r
+\r
+    if (!d)\r
+        return TRUE;\r
 \r
     khui_cw_find_type(d->nc, credtype_id_krb5, &nct);\r
 \r
@@ -154,29 +158,31 @@ k5_handle_wmnc_notify(HWND hwnd,
                 return TRUE;\r
 \r
             /* need to update the controls with d->* */\r
-            if(d->renewable) {\r
-                SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, \r
-                                   BM_SETCHECK, BST_CHECKED, \r
-                                   0);\r
-                EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), \r
-                             TRUE);\r
-            } else {\r
-                SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, \r
-                                   BM_SETCHECK, BST_UNCHECKED, 0);\r
-                EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), \r
-                             FALSE);\r
-            }\r
+            SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, \r
+                               BM_SETCHECK,\r
+                              (d->renewable? BST_CHECKED : BST_UNCHECKED), \r
+                               0);\r
+            EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), \r
+                         !!d->renewable);\r
 \r
             khui_tracker_refresh(&d->tc_lifetime);\r
             khui_tracker_refresh(&d->tc_renew);\r
 \r
-            if(d->forwardable) {\r
-                SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, \r
-                                   BM_SETCHECK, BST_CHECKED, 0);\r
-            } else {\r
-                SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, \r
-                                   BM_SETCHECK, BST_UNCHECKED, 0);\r
-            }\r
+            SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, \r
+                               BM_SETCHECK,\r
+                               (d->forwardable ? BST_CHECKED : BST_UNCHECKED),\r
+                               0);\r
+\r
+            SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,\r
+                               BM_SETCHECK,\r
+                               (d->addressless ? BST_CHECKED : BST_UNCHECKED),\r
+                               0);\r
+\r
+            SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,\r
+                               IPM_SETADDRESS,\r
+                               0, d->publicIP);\r
+\r
+            EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);\r
         }\r
         break;\r
 \r
@@ -280,15 +286,45 @@ k5_handle_wmnc_notify(HWND hwnd,
             d = (k5_dlg_data *)(LONG_PTR) \r
                 GetWindowLongPtr(hwnd, DWLP_USER);\r
 \r
-            if(d->dirty) {\r
+            if(!d->sync) {\r
                 kmq_post_sub_msg(k5_sub, KMSG_CRED, \r
                                  KMSG_CRED_DIALOG_NEW_OPTIONS, \r
                                  0, (void *) d->nc);\r
 \r
-                /* the above notification effectively takes\r
-                   all our changes into account.  The data we\r
-                   have is no longer dirty */\r
-                d->dirty = FALSE;\r
+                /* the above notification effectively takes all our\r
+                   changes into account.  The data we have is no\r
+                   longer out of sync */\r
+                d->sync = FALSE;\r
+            }\r
+        }\r
+        break;\r
+\r
+    case K5_SET_CRED_MSG:\r
+        {\r
+            k5_dlg_data * d;\r
+            khm_size cb;\r
+            wchar_t * msg;\r
+\r
+            d = (k5_dlg_data *) (LONG_PTR)\r
+                GetWindowLongPtr(hwnd, DWLP_USER);\r
+\r
+            msg = (wchar_t *) lParam;\r
+\r
+            if (d->cred_message) {\r
+                PFREE(d->cred_message);\r
+                d->cred_message = NULL;\r
+            }\r
+\r
+            if (msg &&\r
+                SUCCEEDED(StringCbLength(msg,\r
+                                         KHUI_MAXCB_MESSAGE,\r
+                                         &cb))) {\r
+                cb += sizeof(wchar_t);\r
+                d->cred_message = PMALLOC(cb);\r
+#ifdef DEBUG\r
+                assert(d->cred_message);\r
+#endif\r
+                StringCbCopy(d->cred_message, cb, msg);\r
             }\r
         }\r
         break;\r
@@ -297,6 +333,32 @@ k5_handle_wmnc_notify(HWND hwnd,
     return 0;\r
 }\r
 \r
+INT_PTR\r
+k5_handle_wm_notify(HWND hwnd,\r
+                    WPARAM wParam,\r
+                    LPARAM lParam) {\r
+    LPNMHDR pnmh;\r
+    k5_dlg_data * d;\r
+\r
+    pnmh = (LPNMHDR) lParam;\r
+    if (pnmh->idFrom == IDC_NCK5_PUBLICIP &&\r
+        pnmh->code == IPN_FIELDCHANGED) {\r
+\r
+        d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);\r
+\r
+        SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,\r
+                           IPM_GETADDRESS,\r
+                           0, (LPARAM) &d->publicIP);\r
+\r
+        d->dirty = TRUE;\r
+        d->sync = FALSE;\r
+\r
+        return TRUE;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
 INT_PTR\r
 k5_handle_wm_command(HWND hwnd,\r
                      WPARAM wParam,\r
@@ -323,9 +385,10 @@ k5_handle_wm_command(HWND hwnd,
             d->renewable = FALSE;\r
         }\r
         d->dirty = TRUE;\r
+        d->sync = FALSE;\r
     } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) {\r
         int c;\r
-        c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, \r
+        c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, \r
                                      BM_GETCHECK, 0, 0);\r
         if(c==BST_CHECKED) {\r
             d->forwardable = TRUE;\r
@@ -333,6 +396,26 @@ k5_handle_wm_command(HWND hwnd,
             d->forwardable = FALSE;\r
         }\r
         d->dirty = TRUE;\r
+        d->sync = FALSE;\r
+    } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) {\r
+        int c;\r
+\r
+        c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,\r
+                                     BM_GETCHECK, 0, 0);\r
+\r
+        if (c==BST_CHECKED) {\r
+            d->addressless = TRUE;\r
+        } else {\r
+            d->addressless = FALSE;\r
+        }\r
+        d->dirty = TRUE;\r
+        d->sync = FALSE;\r
+\r
+        EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);\r
+    } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT ||\r
+                                      cid == IDC_NCK5_LIFETIME_EDIT)) {\r
+        d->dirty = TRUE;\r
+        d->sync = FALSE;\r
     } else if((notif == CBN_SELCHANGE || \r
                notif == CBN_KILLFOCUS) && \r
               cid == IDC_NCK5_REALM &&\r
@@ -414,6 +497,9 @@ k5_nc_dlg_proc(HWND hwnd,
     case KHUI_WM_NC_NOTIFY:\r
         return k5_handle_wmnc_notify(hwnd, wParam, lParam);\r
 \r
+    case WM_NOTIFY:\r
+        return k5_handle_wm_notify(hwnd, wParam, lParam);\r
+\r
     case WM_DESTROY:\r
         return k5_handle_wm_destroy(hwnd, wParam, lParam);\r
     }\r
@@ -464,19 +550,19 @@ k5_kinit_fiber_proc(PVOID lpParameter)
                 }\r
             }\r
 \r
-            g_fjob.code = khm_krb5_kinit(\r
-                0,\r
-                g_fjob.principal,\r
-                g_fjob.password,\r
-                g_fjob.ccache,\r
-                g_fjob.lifetime,\r
-                g_fjob.forwardable,\r
-                g_fjob.proxiable,\r
-                (g_fjob.renewable ? g_fjob.renew_life : 0),\r
-                g_fjob.addressless,\r
-                g_fjob.publicIP,\r
-                k5_kinit_prompter,\r
-                &g_fjob);\r
+            g_fjob.code =\r
+                khm_krb5_kinit(0,\r
+                               g_fjob.principal,\r
+                               g_fjob.password,\r
+                               g_fjob.ccache,\r
+                               g_fjob.lifetime,\r
+                               g_fjob.forwardable,\r
+                               g_fjob.proxiable,\r
+                               (g_fjob.renewable ? g_fjob.renew_life : 0),\r
+                               g_fjob.addressless,\r
+                               g_fjob.publicIP,\r
+                               k5_kinit_prompter,\r
+                               &g_fjob);\r
         }\r
 \r
     _switch_to_main:\r
@@ -1027,6 +1113,7 @@ k5_read_dlg_params(khm_handle conf,
     khc_read_int32(conf, L"Forwardable", &d->forwardable);\r
     khc_read_int32(conf, L"Proxiable", &d->proxiable);\r
     khc_read_int32(conf, L"Addressless", &d->addressless);\r
+    khc_read_int32(conf, L"PublicIP", &d->publicIP);\r
 \r
     khc_read_int32(conf, L"DefaultLifetime", &i);\r
     d->tc_lifetime.current = i;\r
@@ -1079,6 +1166,7 @@ k5_write_dlg_params(khm_handle conf,
     khc_write_int32(conf, L"Forwardable", d->forwardable);\r
     khc_write_int32(conf, L"Proxiable", d->proxiable);\r
     khc_write_int32(conf, L"Addressless", d->addressless);\r
+    khc_write_int32(conf, L"PublicIP", d->publicIP);\r
 \r
     khc_write_int32(conf, L"DefaultLifetime", \r
                     (khm_int32) d->tc_lifetime.current);\r
@@ -1117,6 +1205,9 @@ k5_prep_kinit_job(khui_new_creds * nc)
     d = (k5_dlg_data *)(LONG_PTR) \r
         GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);\r
 \r
+    if (!d)\r
+       return;\r
+\r
     khui_cw_lock_nc(nc);\r
     ident = nc->identities[0];\r
     kcdb_identity_hold(ident);\r
@@ -1141,7 +1232,7 @@ k5_prep_kinit_job(khui_new_creds * nc)
     g_fjob.renewable = d->renewable;\r
     g_fjob.renew_life = (krb5_deltat) d->tc_renew.current;\r
     g_fjob.addressless = d->addressless;\r
-    g_fjob.publicIP = 0;\r
+    g_fjob.publicIP = d->publicIP;\r
     g_fjob.code = 0;\r
     g_fjob.identity = ident;\r
     g_fjob.prompt_set = 0;\r
@@ -1238,7 +1329,8 @@ k5_find_tgt_filter(khm_handle cred,
                                            &cident)) &&\r
         cident == ident &&\r
         KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) &&\r
-        (f & KCDB_CRED_FLAG_INITIAL))\r
+        (f & KCDB_CRED_FLAG_INITIAL) &&\r
+        !(f & KCDB_CRED_FLAG_EXPIRED))\r
         rv = 1;\r
     else\r
         rv = 0;\r
@@ -1406,7 +1498,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                hasn't changed the options */\r
             khui_cw_lock_nc(nc);\r
 \r
-            if(!d->dirty && nc->n_identities > 0 &&\r
+           /* ?: It might be better to not load identity defaults if\r
+              the user has already changed options in the dialog. */\r
+            if(/* !d->dirty && */ nc->n_identities > 0 &&\r
                nc->subtype == KMSG_CRED_NEW_CREDS) {\r
 \r
                 khm_handle h_id = NULL;\r
@@ -1648,7 +1742,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                         assert(g_fjob.state == FIBER_STATE_NONE);\r
 #endif\r
                         g_fjob.code = 0;\r
-                    } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {\r
+\r
+                       _reportf(L"Cancelling");\r
+                    } else if (nc->result == KHUI_NC_RESULT_PROCESS) {\r
                         khui_cw_sync_prompt_values(nc);\r
                         g_fjob.command = FIBER_CMD_CONTINUE;\r
                         SwitchToFiber(k5_kinit_fiber);\r
@@ -1666,7 +1762,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                     if (nc->result == KHUI_NC_RESULT_CANCEL) {\r
                         /* nothing to report */\r
                         g_fjob.code = 0;\r
-                    } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {\r
+                    } else if (nc->result == KHUI_NC_RESULT_PROCESS) {\r
                         /* g_fjob.code should have the result of the\r
                            last kinit attempt.  We should leave it\r
                            as-is */\r
@@ -1694,8 +1790,10 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                                     k5_find_tgt_filter,\r
                                     nc->identities[0],\r
                                     NULL,\r
-                                    NULL))))\r
+                                    NULL)))) {\r
+                   _reportf(L"No password entered, but a valid TGT exists. Continuing");\r
                     g_fjob.code = 0;\r
+               }\r
 \r
                 if(g_fjob.code != 0) {\r
                     wchar_t tbuf[1024];\r
@@ -1722,7 +1820,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                     assert(g_fjob.state == FIBER_STATE_NONE);\r
 #endif\r
 \r
-                } else if (nc->result == KHUI_NC_RESULT_GET_CREDS &&\r
+                } else if (nc->result == KHUI_NC_RESULT_PROCESS &&\r
                            g_fjob.state == FIBER_STATE_NONE) {\r
                     khm_handle sp = NULL;\r
                     khm_handle ep = NULL;\r
@@ -1734,6 +1832,8 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                     khm_size cb_ms;\r
                     khm_int32 rv;\r
 \r
+                   _reportf(L"Tickets successfully acquired");\r
+\r
                     r = KHUI_NC_RESPONSE_SUCCESS |\r
                         KHUI_NC_RESPONSE_EXIT;\r
 \r
@@ -1770,6 +1870,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                     khm_krb5_list_tickets(&ctx);\r
 \r
                     if (nc->set_default) {\r
+                       _reportf(L"Setting default identity");\r
                         kcdb_identity_set_default(nc->identities[0]);\r
                     }\r
 \r
@@ -1781,6 +1882,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                         if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {\r
                             kcdb_identity_release(tdefault);\r
                         } else {\r
+                           _reportf(L"There was no default identity.  Setting default");\r
                             kcdb_identity_set_default(nc->identities[0]);\r
                         }\r
                     }\r
@@ -1957,10 +2059,29 @@ k5_msg_cred_dialog(khm_int32 msg_type,
 \r
                 if (nc->ctx.scope == KHUI_SCOPE_IDENT ||\r
                     (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&\r
-                     nc->ctx.cred_type == credtype_id_krb5)) {\r
+                     nc->ctx.cred_type == credtype_id_krb5) ||\r
+                   (nc->ctx.scope == KHUI_SCOPE_CRED &&\r
+                    nc->ctx.cred_type == credtype_id_krb5)) {\r
                     int code;\r
 \r
-                    if (nc->ctx.identity != 0) {\r
+                   if (nc->ctx.scope == KHUI_SCOPE_CRED &&\r
+                       nc->ctx.cred != NULL) {\r
+\r
+                       /* get the expiration time for the identity first. */\r
+                       cb = sizeof(ftidexp);\r
+#ifdef DEBUG\r
+                       assert(nc->ctx.identity != NULL);\r
+#endif\r
+                       kcdb_identity_get_attr(nc->ctx.identity,\r
+                                              KCDB_ATTR_EXPIRE,\r
+                                              NULL,\r
+                                              &ftidexp,\r
+                                              &cb);\r
+\r
+                       code = khm_krb5_renew_cred(nc->ctx.cred);\r
+\r
+                    } else if (nc->ctx.scope == KHUI_SCOPE_IDENT &&\r
+                              nc->ctx.identity != 0) {\r
                         /* get the current identity expiration time */\r
                         cb = sizeof(ftidexp);\r
 \r
@@ -1970,12 +2091,17 @@ k5_msg_cred_dialog(khm_int32 msg_type,
                                                &ftidexp,\r
                                                &cb);\r
 \r
-                        code = khm_krb5_renew(nc->ctx.identity);\r
+                        code = khm_krb5_renew_ident(nc->ctx.identity);\r
                     } else {\r
+\r
+                       _reportf(L"No identity specified.  Can't renew Kerberos tickets");\r
+\r
                         code = 1; /* it just has to be non-zero */\r
                     }\r
 \r
                     if (code == 0) {\r
+                       _reportf(L"Tickets successfully renewed");\r
+\r
                         khui_cw_set_response(nc, credtype_id_krb5, \r
                                              KHUI_NC_RESPONSE_EXIT | \r
                                              KHUI_NC_RESPONSE_SUCCESS);\r
@@ -2035,7 +2161,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
 \r
                 _end_task();\r
             } else if (nc->subtype == KMSG_CRED_PASSWORD &&\r
-                       nc->result == KHUI_NC_RESULT_GET_CREDS) {\r
+                       nc->result == KHUI_NC_RESULT_PROCESS) {\r
 \r
                 _begin_task(0);\r
                 _report_mr0(KHERR_NONE, MSG_CTX_PASSWD);\r
index e58e69f346659f37f5a6a4996c982a57bac0257b..7c5287769ca08a61c3089f1b1aabf35fc89fdda9 100644 (file)
@@ -134,23 +134,21 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
 \r
         k5_unregister_config_panels();\r
 \r
-        if(credtype_id_krb5 >= 0)\r
-            {\r
-                /* basically just unregister the credential type */\r
-                kcdb_credtype_unregister(credtype_id_krb5);\r
-\r
-                /* kcdb knows how to deal with bad handles */\r
-                kcdb_credset_delete(krb5_credset);\r
-                krb5_credset = NULL;\r
-            }\r
+        if(credtype_id_krb5 >= 0) {\r
+            /* basically just unregister the credential type */\r
+            kcdb_credtype_unregister(credtype_id_krb5);\r
 \r
-        if(k5_main_fiber != NULL) {\r
+            /* kcdb knows how to deal with bad handles */\r
+            kcdb_credset_delete(krb5_credset);\r
+            krb5_credset = NULL;\r
+        }\r
 \r
+        if(k5_main_fiber != NULL) {\r
             if (k5_kinit_fiber) {\r
 #ifdef DEBUG\r
                 assert(k5_kinit_fiber != GetCurrentFiber());\r
 #endif\r
-#if CLEANUP_FIBERS_ON_EXIT\r
+#ifdef CLEANUP_FIBERS_ON_EXIT\r
                 DeleteFiber(k5_kinit_fiber);\r
                 CloseHandle(k5_kinit_fiber);\r
 #endif\r
@@ -158,7 +156,6 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
             }\r
 \r
             k5_main_fiber = NULL;\r
-\r
         }\r
 \r
         if(k5_sub != NULL) {\r
@@ -200,9 +197,16 @@ k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
             khui_action_context * ctx;\r
 \r
             ctx = (khui_action_context *) vparam;\r
-                \r
-            if (ctx->credset)\r
+\r
+            if (ctx->credset) {\r
+                _begin_task(0);\r
+                _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS);\r
+                _describe();\r
+\r
                 khm_krb5_destroy_by_credset(ctx->credset);\r
+\r
+                _end_task();\r
+            }\r
         }\r
         break;\r
 \r
index 9b849c88ff00f08167427b680a624142c8135f4e..49da4f2df4c21830907d8dd4054914679179718d 100644 (file)
@@ -13,9 +13,10 @@ Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider
     DefaultLifetime,KC_INT32,36000,Default ticket lifetime\r
     MaxLifetime,KC_INT32,86400,Maximum lifetime\r
     MinLifetime,KC_INT32,60,Minimum lifetime\r
-    Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean)\r
+    Forwardable,KC_INT32,0,Obtain forwardable tickets (boolean)\r
     Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean)\r
     Addressless,KC_INT32,1,Obtain addressless tickets (boolean)\r
+    PublicIP,KC_INT32,0,Additional public IP address to use (int32)\r
     Renewable,KC_INT32,1,Obtain renewable tickets (boolean)\r
     DefaultRenewLifetime,KC_INT32,604800,Default renewable lifetime\r
     MaxRenewLifetime,KC_INT32,2592000,Maximum renewable lifetime\r
index 7ab035c8c9227f9f0d1aebc9706dfac8d4ccea28..3e64b00772e8f3491c3ff1d440164af011c8c650 100644 (file)
@@ -180,6 +180,8 @@ extern fiber_job g_fjob;   /* global fiber job object */
 #define FIBER_STATE_NONE    0\r
 #define FIBER_STATE_KINIT   1\r
 \r
+#define K5_SET_CRED_MSG     WMNC_USER\r
+\r
 void \r
 k5_pp_begin(khui_property_sheet * s);\r
 \r
index d54fc101e0d29fe4e8b79aaf0828b9412d7c6f2f..c54bdb4b1aafbeb4a0d1fa3ea5affef51481b1fe 100644 (file)
@@ -58,6 +58,8 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS |
 EXSTYLE WS_EX_CONTROLPARENT\r
 FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
 BEGIN\r
+    CONTROL         "Kerberos 5 Ticket Options",IDC_STATIC,"Static",\r
+                    SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11\r
     LTEXT           "Realm",IDC_STATIC,7,25,52,13\r
     COMBOBOX        IDC_NCK5_REALM,60,25,233,17,CBS_DROPDOWN | \r
                     CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP\r
@@ -71,8 +73,12 @@ BEGIN
     CONTROL         "Can be &forwarded to other machines",\r
                     IDC_NCK5_FORWARDABLE,"Button",BS_AUTOCHECKBOX | \r
                     BS_NOTIFY | WS_TABSTOP,7,107,132,12\r
-    CONTROL         "Kerberos 5 Ticket Options",IDC_STATIC,"Static",\r
-                    SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11\r
+    CONTROL         "Addressless",IDC_NCK5_ADDRESS,"Button",BS_AUTOCHECKBOX | \r
+                    WS_TABSTOP,7,128,54,10\r
+    LTEXT           "Additional IP address",IDC_STATIC,118,129,68,8,NOT \r
+                    WS_VISIBLE\r
+    CONTROL         "",IDC_NCK5_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE | \r
+                    WS_TABSTOP,193,125,100,15\r
 END\r
 \r
 IDD_PP_KRB5C DIALOGEX 0, 0, 235, 156\r
@@ -129,18 +135,19 @@ BEGIN
     LTEXT           "Default Realm",IDC_CFG_LBL_REALM,13,9,46,8\r
     COMBOBOX        IDC_CFG_DEFREALM,76,7,166,30,CBS_DROPDOWN | CBS_SORT | \r
                     WS_VSCROLL | WS_TABSTOP\r
-    PUSHBUTTON      "Configure Realms ...",IDC_CFG_CFGREALMS,76,25,84,14,\r
-                    WS_DISABLED\r
+    PUSHBUTTON      "Configure Realms ...",IDC_CFG_CFGREALMS,76,25,84,14,NOT \r
+                    WS_VISIBLE | WS_DISABLED\r
     GROUPBOX        "Keberos Configuration File",IDC_CFG_CFGFILEGRP,7,45,241,\r
                     61\r
     LTEXT           "Location",IDC_CFG_LBL_CFGFILE,13,61,28,8\r
     EDITTEXT        IDC_CFG_CFGFILE,76,58,119,14,ES_AUTOHSCROLL\r
     PUSHBUTTON      "Browse...",IDC_CFG_BROWSE,198,58,44,14\r
     CONTROL         "Create file if missing",IDC_CFG_CREATECONFIG,"Button",\r
-                    BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,76,76,80,10\r
+                    BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | \r
+                    WS_TABSTOP,76,90,80,10\r
     CONTROL         "Include realms in New Credentials realm list",\r
                     IDC_CFG_INCREALMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,\r
-                    76,91,153,10\r
+                    76,78,153,10\r
     GROUPBOX        "Windows® Options",IDC_CFG_WINGRP,7,110,241,65\r
     LTEXT           "Hostname",IDC_CFG_LBL_HOSTNAME,13,123,33,8\r
     EDITTEXT        IDC_CFG_HOSTNAME,76,120,166,14,ES_AUTOHSCROLL | \r
@@ -200,11 +207,19 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN\r
     LTEXT           "Ticket lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8\r
     EDITTEXT        IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL\r
-    LTEXT           "Ticket renewable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,\r
-                    8\r
-    EDITTEXT        IDC_CFG_DEFRLIFE,91,26,137,14,ES_AUTOHSCROLL\r
-    LTEXT           "Credentials cache",IDC_STATIC,7,63,58,8\r
-    EDITTEXT        IDC_CFG_CCACHE,91,60,137,14,ES_AUTOHSCROLL\r
+    CONTROL         "Renewable for",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | \r
+                    WS_TABSTOP,7,41,63,10\r
+    EDITTEXT        IDC_CFG_DEFRLIFE,91,39,137,14,ES_AUTOHSCROLL\r
+    CONTROL         "Can be forwarded to other machines",IDC_CFG_FORWARD,\r
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,59,133,10\r
+    CONTROL         "Addressless",IDC_CFG_ADDRESSLESS,"Button",\r
+                    BS_AUTOCHECKBOX | WS_TABSTOP,7,77,54,10\r
+    LTEXT           "Additional IP address",IDC_STATIC,91,78,68,8,NOT \r
+                    WS_VISIBLE\r
+    CONTROL         "",IDC_CFG_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE | \r
+                    WS_TABSTOP,128,89,100,15\r
+    LTEXT           "Credentials cache",IDC_STATIC,7,132,58,8\r
+    EDITTEXT        IDC_CFG_CCACHE,91,130,137,14,ES_AUTOHSCROLL\r
 END\r
 \r
 IDD_NC_KRB5_PASSWORD DIALOGEX 0, 0, 300, 166\r
@@ -226,18 +241,19 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
 EXSTYLE WS_EX_CONTROLPARENT\r
 FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
 BEGIN\r
-    GROUPBOX        "File Caches",IDC_CFG_FCGRP,7,38,241,137\r
+    GROUPBOX        "File Caches",IDC_CFG_FCGRP,7,26,241,149\r
     CONTROL         "",IDC_CFG_FCLIST,"SysListView32",LVS_REPORT | \r
                     LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | \r
-                    WS_TABSTOP,13,48,229,86\r
+                    WS_TABSTOP,13,37,229,97\r
     EDITTEXT        IDC_CFG_FCNAME,13,139,173,14,ES_AUTOHSCROLL\r
     PUSHBUTTON      "&Browse ...",IDC_CFG_BROWSE,192,139,50,14\r
     PUSHBUTTON      "Add",IDC_CFG_ADD,13,156,50,14\r
     PUSHBUTTON      "Remove Selected",IDC_CFG_REMOVE,88,156,80,14\r
-    CHECKBOX        "Include all API: credentials caches",IDC_CFG_INCAPI,13,\r
-                    7,125,10\r
+    CONTROL         "Include all API: credentials caches",IDC_CFG_INCAPI,\r
+                    "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,\r
+                    123,7,125,10\r
     CONTROL         "Include Windows LSA cache (MSLSA:)",IDC_CFG_INCMSLSA,\r
-                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,22,136,10\r
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,7,136,10\r
 END\r
 \r
 \r
@@ -396,7 +412,7 @@ STRINGTABLE
 BEGIN\r
     IDS_KRB4_SHORT_DESC     "Kerberos 4"\r
     IDS_KRB4_LONG_DESC      "Kerberos 4 tickets"\r
-    IDS_KRB5_FLAGS_SHORT_DESC "Flags"\r
+    IDS_KRB5_FLAGS_SHORT_DESC "Krb5 Flags"\r
     IDS_RENEW_TILL_SHORT_DESC "Renew Till"\r
     IDS_RENEW_TILL_LONG_DESC "Renewable Till"\r
     IDS_RENEW_FOR_SHORT_DESC "Renew for"\r
@@ -484,6 +500,27 @@ BEGIN
     IDS_CFG_RE_NEWSERVER    "<New server...>"\r
     IDS_CFG_RE_NEWDMAP      "<New domain mapping...>"\r
     IDS_KRB5_NC_NAME        "Kerberos 5"\r
+    IDS_NCERR_IDENT_TOO_LONG "The identity name is too long."\r
+    IDS_NCERR_IDENT_INVALID "The identity name is invalid."\r
+    IDS_NCERR_IDENT_UNKNOWN "An unknown error occurred while validating the identity name."\r
+    IDS_CFG_RE_ARNUT        "Can't add new realm %s"\r
+    IDS_CFG_RE_ARNUM        "The new realm name %s can't be added because there is already a realm with the same name listed.  Please type another name."\r
+    IDS_CFG_RE_ASNUT        "Can't add new server %s for realm %s"\r
+    IDS_CFG_RE_ASNUM        "There already is a server named %s for realm %s. The new server can not be added."\r
+    IDS_CFG_RE_DMNUT        "Can't add new domain map %s for realm %s"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_CFG_RE_DMNUM        "There already is a domain named %s mapping to realm %s.  The new domain map could not be added."\r
+    IDS_CFG_RE_MNR          "&Add new realm"\r
+    IDS_CFG_RE_MDR          "&Remove realm"\r
+    IDS_CFG_RE_MNK          "&Add new server"\r
+    IDS_CFG_RE_MDK          "&Remove server"\r
+    IDS_CFG_RE_MAK          "Toggle a&dmin server"\r
+    IDS_CFG_RE_MMK          "Toggle &master KDC"\r
+    IDS_CFG_RE_MND          "&Add new domain mapping"\r
+    IDS_CFG_RE_MDD          "&Remove domain mapping"\r
 END\r
 \r
 #endif    // English (U.S.) resources\r
index 2b637ac9fb4d618f60a5720059a9dfc472c58dd5..01e01761fd5251f5e6dce2f9e64cf6e80b2eedb1 100644 (file)
@@ -151,6 +151,11 @@ Language=English
 This is commonly caused by an incorrect password.  Please verify that the password is correct and note that passwords are case sensitive.\r
 .\r
 \r
+MessageId=\r
+SymbolicName=MSG_ERR_CTX_DESTROY_CREDS\r
+Language=English\r
+Destroying Krb5 tickets\r
+.\r
 \r
 MessageId=\r
 SymbolicName=MSG_\r
index 6f76cc56bb28069289a898b02ff77a6b31f25ba0..edda7dd02dd50412aa90737f8a49d6904602a1f6 100644 (file)
@@ -1,6 +1,6 @@
 //{{NO_DEPENDENCIES}}\r
 // Microsoft Visual C++ generated include file.\r
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc\r
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc\r
 //\r
 #define IDS_UNK_ADDR_FMT                101\r
 #define IDD_NC_KRB5                     102\r
 #define IDS_CFG_RE_NEWSERVER            197\r
 #define IDS_CFG_RE_NEWDMAP              198\r
 #define IDS_KRB5_NC_NAME                199\r
+#define IDS_NCERR_IDENT_TOO_LONG        200\r
+#define IDS_NCERR_IDENT_INVALID         201\r
+#define IDS_NCERR_IDENT_UNKNOWN         202\r
+#define IDS_CFG_RE_ARNUT                203\r
+#define IDS_CFG_RE_ARNUM                204\r
+#define IDS_CFG_RE_ASNUT                205\r
+#define IDS_CFG_RE_ASNUM                206\r
+#define IDS_CFG_RE_DMNUT                207\r
+#define IDS_CFG_RE_DMNUM                208\r
+#define IDS_CFG_RE_MNR                  209\r
+#define IDS_CFG_RE_MDR                  210\r
+#define IDS_CFG_RE_MNK                  211\r
+#define IDS_CFG_RE_MDK                  212\r
+#define IDS_CFG_RE_MAK                  213\r
+#define IDS_CFG_RE_MMK                  214\r
+#define IDS_CFG_RE_MND                  215\r
+#define IDS_CFG_RE_MDD                  216\r
 #define IDC_NCK5_RENEWABLE              1002\r
 #define IDC_NCK5_FORWARDABLE            1004\r
 #define IDC_NCK5_REALM                  1005\r
 #define IDC_CFG_INCAPI                  1066\r
 #define IDC_CFG_INCMSLSA                1067\r
 #define IDC_PPK5_FLAGS                  1072\r
-#define IDC_CHECK1                      1073\r
 #define IDC_CFG_INCREALMS               1073\r
+#define IDC_NCK5_ADDRESS                1074\r
+#define IDC_IPADDRESS1                  1075\r
+#define IDC_NCK5_PUBLICIP               1075\r
+#define IDC_CFG_PUBLICIP                1075\r
+#define IDC_CFG_RENEW                   1076\r
+#define IDC_CHECK3                      1077\r
+#define IDC_CFG_ADDRESSLESS             1077\r
+#define IDC_CFG_FORWARD                 1078\r
+#define ID_FOO_BAR                      40001\r
 \r
 // Next default values for new objects\r
 // \r
 #ifdef APSTUDIO_INVOKED\r
 #ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        117\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1074\r
+#define _APS_NEXT_RESOURCE_VALUE        118\r
+#define _APS_NEXT_COMMAND_VALUE         40002\r
+#define _APS_NEXT_CONTROL_VALUE         1079\r
 #define _APS_NEXT_SYMED_VALUE           101\r
 #endif\r
 #endif\r
index 10b16dd293d3c73059ef3d19e563ceee9b153b12..ec58aa90b63587d3736a8046cad330484be03dd6 100644 (file)
 \r
 #include<netidmgr_intver.h>\r
 \r
+#ifndef LANGVER\r
+\r
+#define STR_FILEDESC "Kerberos 5 Plugin for NetIDMgr"\r
+#define STR_INTNAME  "krb5cred"\r
+#define STR_ORIGNAME "krb5cred.dll"\r
+\r
+#else\r
+\r
+#ifdef LANG_en_us\r
+\r
+#define STR_FILEDESC "English(US) language resources for the Keberos 5 plugin"\r
+#define STR_INTNAME  "krb5cred_en_us"\r
+#define STR_ORIGNAME "krb5cred_en_us.dll"\r
+\r
+#else\r
+\r
+#error Unknown langugae\r
+\r
+#endif\r
+\r
+#endif\r
+\r
 1 VERSIONINFO \r
         FILEVERSION     KH_VERSION_LIST\r
         PRODUCTVERSION  KH_VERSION_LIST\r
       BLOCK "040904b0"\r
       {\r
         VALUE "CompanyName",     KH_VERSTR_COMPANY_1033\r
-        VALUE "FileDescription", "Kerberos 5 plugin for NetIDMgr"\r
+        VALUE "FileDescription", STR_FILEDESC\r
         VALUE "FileVersion",     KH_VERSTR_VERSION_1033\r
-        VALUE "InternalName",    "krb5cred"\r
+        VALUE "InternalName",    STR_INTNAME\r
         VALUE "LegalCopyright",  KH_VERSTR_COPYRIGHT_1033\r
-        VALUE "OriginalFilename", "krb5cred.dll"\r
+        VALUE "OriginalFilename", STR_ORIGNAME\r
         VALUE "ProductName",     "NetIDMgr"\r
         VALUE "ProductVersion",  KH_VERSTR_PRODUCT_1033\r
 #ifdef KH_VERSTR_COMMENT_1033\r
         VALUE "Comment", KH_VERSTR_COMMENT_1033\r
 #endif\r
+#ifndef LANGVER\r
         VALUE NIMV_MODULE,       "MITKrb5"\r
         VALUE NIMV_PLUGINS,      "Krb5Cred,Krb5Ident"\r
         VALUE NIMV_APIVER,       KH_VERSION_STRINGAPI\r
         VALUE NIMV_SUPPORT,      "http://web.mit.edu/kerberos"\r
+#endif\r
       }\r
     }\r
 \r
index 7b3acc40f4c654f4c154b6726774c341a50807ba..c2a78e21baeb57c60822e8241994de740a716194 100644 (file)
-#\r
-# Copyright (c) 2004 Massachusetts Institute of Technology\r
-#\r
-# Permission is hereby granted, free of charge, to any person\r
-# obtaining a copy of this software and associated documentation files\r
-# (the "Software"), to deal in the Software without restriction,\r
-# including without limitation the rights to use, copy, modify, merge,\r
-# publish, distribute, sublicense, and/or sell copies of the Software,\r
-# and to permit persons to whom the Software is furnished to do so,\r
-# subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be\r
-# included in all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-# SOFTWARE.\r
-\r
-\r
-MODULE=ui\r
-!include <../config/Makefile.w32>\r
-\r
-EXEFILE=$(BINDIR)\netidmgr.exe\r
-\r
-MANIFESTFILE=$(BINDIR)\netidmgr.exe.manifest\r
-\r
-OBJFILES=                      \\r
-       $(OBJ)\main.obj         \\r
-       $(OBJ)\mainmenu.obj     \\r
-       $(OBJ)\toolbar.obj      \\r
-       $(OBJ)\statusbar.obj    \\r
-       $(OBJ)\notifier.obj     \\r
-       $(OBJ)\timer.obj        \\r
-       $(OBJ)\uiconfig.obj     \\r
-       $(OBJ)\mainwnd.obj      \\r
-       $(OBJ)\credwnd.obj      \\r
-       $(OBJ)\htwnd.obj        \\r
-       $(OBJ)\passwnd.obj      \\r
-       $(OBJ)\newcredwnd.obj   \\r
-       $(OBJ)\propertywnd.obj  \\r
-       $(OBJ)\credfuncs.obj    \\r
-       $(OBJ)\configwnd.obj    \\r
-       $(OBJ)\aboutwnd.obj     \\r
-       $(OBJ)\reqdaemon.obj    \\r
-       $(OBJ)\addrchange.obj   \\r
-       $(OBJ)\cfg_general_wnd.obj \\r
-       $(OBJ)\cfg_identities_wnd.obj \\r
-       $(OBJ)\cfg_notif_wnd.obj \\r
-       $(OBJ)\cfg_plugins_wnd.obj\r
-\r
-RESFILES= \\r
-       $(OBJ)\khapp.res        \\r
-       $(OBJ)\appver.res\r
-\r
-LIBFILES=                      \\r
-       $(LIBDIR)\nidmgr32.lib\r
-\r
-SDKLIBFILES=                   \\r
-       comctl32.lib            \\r
-       shell32.lib             \\r
-       htmlhelp.lib            \\r
-       iphlpapi.lib            \\r
-       shlwapi.lib\r
-\r
-$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg\r
-       $(CCSV) $** $@\r
-\r
-$(OBJ)\khapp.res: lang\en_us\khapp.rc\r
-       $(RC2RES)\r
-\r
-$(OBJ)\appver.res: appver.rc\r
-       $(RC2RES)\r
-\r
-!if "$(KH_BUILD)"=="RETAIL"\r
-$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER)\r
-!else\r
-$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER).debug\r
-!endif\r
-       $(CP) $** $@\r
-\r
-$(EXEFILE): $(OBJFILES) $(RESFILES) $(LIBFILES)\r
-       $(EXEGUILINK) $(SDKLIBFILES)\r
-\r
-all: mkdirs $(EXEFILE) $(MANIFESTFILE)\r
-\r
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=ui
+!include <../config/Makefile.w32>
+
+EXEFILE=$(BINDIR)\netidmgr.exe
+
+MANIFESTFILE=$(BINDIR)\netidmgr.exe.manifest
+
+OBJFILES=                      \
+       $(OBJ)\main.obj         \
+       $(OBJ)\mainmenu.obj     \
+       $(OBJ)\toolbar.obj      \
+       $(OBJ)\statusbar.obj    \
+       $(OBJ)\notifier.obj     \
+       $(OBJ)\timer.obj        \
+       $(OBJ)\uiconfig.obj     \
+       $(OBJ)\mainwnd.obj      \
+       $(OBJ)\credwnd.obj      \
+       $(OBJ)\htwnd.obj        \
+       $(OBJ)\passwnd.obj      \
+       $(OBJ)\newcredwnd.obj   \
+       $(OBJ)\propertywnd.obj  \
+       $(OBJ)\credfuncs.obj    \
+       $(OBJ)\configwnd.obj    \
+       $(OBJ)\aboutwnd.obj     \
+       $(OBJ)\reqdaemon.obj    \
+       $(OBJ)\addrchange.obj   \
+       $(OBJ)\debugfuncs.obj   \
+       $(OBJ)\cfg_general_wnd.obj \
+       $(OBJ)\cfg_identities_wnd.obj \
+       $(OBJ)\cfg_notif_wnd.obj \
+       $(OBJ)\cfg_plugins_wnd.obj
+
+RESFILES= \
+       $(OBJ)\khapp.res        \
+       $(OBJ)\appver.res
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+LIBFILES=$(LIBDIR)\nidmgr64.lib
+!else
+LIBFILES=$(LIBDIR)\nidmgr32.lib
+!endif
+
+SDKLIBFILES=                   \
+       comctl32.lib            \
+       shell32.lib             \
+       htmlhelp.lib            \
+       iphlpapi.lib            \
+       shlwapi.lib
+
+$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg
+       $(CCSV) $** $@
+
+$(OBJ)\khapp.res: lang\en_us\khapp.rc
+       $(RC2RES)
+
+$(OBJ)\appver.res: appver.rc
+       $(RC2RES)
+
+!if "$(KH_BUILD)"=="RETAIL"
+$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER)
+!else
+$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER).debug
+!endif
+       $(CP) $** $@
+
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+!else
+SCLIB=
+!endif
+
+$(EXEFILE): $(OBJFILES) $(RESFILES) $(LIBFILES)
+       $(EXEGUILINK) $(SDKLIBFILES) $(SCLIB)
+
+all: mkdirs $(EXEFILE) $(MANIFESTFILE)
+
index 9baa9b9e2929b9993e17513b6097851697713373..952996107e4aa012394abd5250bc304cb886f180 100644 (file)
@@ -36,10 +36,11 @@ extern int khm_nCmdShow;
 extern const wchar_t * khm_facility;\r
 extern kconf_schema schema_uiconfig[];\r
 extern khm_ui_4 khm_commctl_version;\r
+extern khm_version app_version;\r
 \r
 #define IS_COMMCTL6() (khm_commctl_version >= 0x60000)\r
 \r
-typedef struct tag_khm_startup_options {\r
+typedef struct tag_khm_startup_options_v1 {\r
     BOOL seen;\r
     BOOL processing;\r
 \r
@@ -57,6 +58,19 @@ typedef struct tag_khm_startup_options {
 \r
 extern khm_startup_options khm_startup;\r
 \r
+typedef struct tag_khm_query_app_version_v1 {\r
+    khm_int32 magic;\r
+\r
+    khm_int32 code;\r
+\r
+    khm_version ver_caller;\r
+    khm_version ver_remote;\r
+\r
+    khm_boolean request_swap;\r
+} khm_query_app_version;\r
+\r
+#define KHM_QUERY_APP_VER_MAGIC 0x38f8c2eb\r
+\r
 void khm_add_dialog(HWND dlg);\r
 void khm_del_dialog(HWND dlg);\r
 BOOL khm_is_dialog_active(void);\r
@@ -75,6 +89,8 @@ void khm_register_window_classes(void);
 \r
 HWND khm_html_help(HWND hwnd, wchar_t * suffix, UINT command, DWORD_PTR data);\r
 \r
+WPARAM khm_message_loop_int(khm_boolean * p_exit);\r
+\r
 #define MAX_RES_STRING 1024\r
 \r
 #define ELIPSIS L"..."\r
index 7b48975a974f6af76c109f306f648c508323b218..c01402b84ea6a3ab2a97fe10dff1006d31d8732d 100644 (file)
@@ -33,6 +33,8 @@ typedef struct tag_cfg_data {
     BOOL auto_import;\r
     BOOL keep_running;\r
     BOOL auto_detect_net;\r
+    BOOL log_to_file;\r
+    BOOL destroy_creds;\r
 } cfg_data;\r
 \r
 typedef struct tag_dlg_data {\r
@@ -72,6 +74,12 @@ read_params(dlg_data * dd) {
     khc_read_int32(csp_cw, L"AutoDetectNet", &t);\r
     d->auto_detect_net = !!t;\r
 \r
+    khc_read_int32(csp_cw, L"LogToFile", &t);\r
+    d->log_to_file = !!t;\r
+\r
+    khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t);\r
+    d->destroy_creds = !!t;\r
+\r
     khc_close_space(csp_cw);\r
 \r
     dd->work = *d;\r
@@ -119,6 +127,22 @@ write_params(dlg_data * dd) {
         applied = TRUE;\r
     }\r
 \r
+    if (!!d->log_to_file != !!s->log_to_file) {\r
+       khc_write_int32(csp_cw, L"LogToFile", d->log_to_file);\r
+       applied = TRUE;\r
+\r
+       if (d->log_to_file) {\r
+           khm_start_file_log();\r
+       } else {\r
+           khm_stop_file_log();\r
+       }\r
+    }\r
+\r
+    if (!!d->destroy_creds != !!s->destroy_creds) {\r
+        khc_write_int32(csp_cw, L"DestroyCredsOnExit", d->destroy_creds);\r
+        applied = TRUE;\r
+    }\r
+\r
     khc_close_space(csp_cw);\r
 \r
     khui_cfg_set_flags(dd->node,\r
@@ -138,7 +162,9 @@ check_for_modification(dlg_data * dd) {
         !!d->auto_start != !!s->auto_start ||\r
         !!d->auto_import != !!s->auto_import ||\r
         !!d->keep_running != !!s->keep_running ||\r
-        !!d->auto_detect_net != !!s->auto_detect_net) {\r
+        !!d->auto_detect_net != !!s->auto_detect_net ||\r
+       !!d->log_to_file != !!s->log_to_file ||\r
+        !!d->destroy_creds != !!s->destroy_creds) {\r
 \r
         khui_cfg_set_flags(dd->node,\r
                            KHUI_CNFLAG_MODIFIED,\r
@@ -155,6 +181,8 @@ check_for_modification(dlg_data * dd) {
 \r
 static void\r
 refresh_view(HWND hwnd, dlg_data * d) {\r
+    wchar_t buf[512];\r
+\r
     CheckDlgButton(hwnd, IDC_CFG_AUTOINIT,\r
                    (d->work.auto_init?BST_CHECKED:BST_UNCHECKED));\r
     CheckDlgButton(hwnd, IDC_CFG_AUTOSTART,\r
@@ -165,6 +193,20 @@ refresh_view(HWND hwnd, dlg_data * d) {
                    (d->work.keep_running?BST_CHECKED:BST_UNCHECKED));\r
     CheckDlgButton(hwnd, IDC_CFG_NETDETECT,\r
                    (d->work.auto_detect_net?BST_CHECKED:BST_UNCHECKED));\r
+    CheckDlgButton(hwnd, IDC_CFG_LOGTOFILE,\r
+                  (d->work.log_to_file?BST_CHECKED:BST_UNCHECKED));\r
+    CheckDlgButton(hwnd, IDC_CFG_DESTROYALL,\r
+                   (d->work.destroy_creds?BST_CHECKED:BST_UNCHECKED));\r
+\r
+    /* in addition, we correct the label on the trace log control to\r
+       reflect the actual path that is going to get used */\r
+    if (GetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf,\r
+                      ARRAYLENGTH(buf)) == 0) {\r
+\r
+       khm_get_file_log_path(sizeof(buf), buf);\r
+\r
+       SetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf);\r
+    }\r
 }\r
 \r
 static void\r
@@ -179,6 +221,10 @@ refresh_data(HWND hwnd, dlg_data * d) {
                             == BST_CHECKED);\r
     d->work.auto_detect_net = (IsDlgButtonChecked(hwnd, IDC_CFG_NETDETECT)\r
                                == BST_CHECKED);\r
+    d->work.log_to_file = (IsDlgButtonChecked(hwnd, IDC_CFG_LOGTOFILE)\r
+                          == BST_CHECKED);\r
+    d->work.destroy_creds = (IsDlgButtonChecked(hwnd, IDC_CFG_DESTROYALL)\r
+                             == BST_CHECKED);\r
 }\r
 \r
 INT_PTR CALLBACK\r
index 0ec3dcbbba279b94ef995b94eba9a6ababf06aae..26a60e5e0f7c822751be20d29f956fa8aa73607e 100644 (file)
@@ -155,7 +155,7 @@ apply_all(HWND hwnd,
         assert(hw);\r
 #endif\r
 \r
-        PostMessage(hw, KHUI_WM_CFG_NOTIFY,\r
+        SendMessage(hw, KHUI_WM_CFG_NOTIFY,\r
                     MAKEWPARAM(0, WMCFG_APPLY), 0);\r
     }\r
 }\r
@@ -169,6 +169,7 @@ show_tab_panel(HWND hwnd,
     TCITEM tci;\r
     HWND hw;\r
     HWND hw_target;\r
+    HWND hw_firstctl;\r
     RECT r;\r
     RECT rref;\r
     khui_config_node_reg reg;\r
@@ -213,6 +214,11 @@ show_tab_panel(HWND hwnd,
                  r.right - r.left, r.bottom - r.top,\r
                  SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
                  SWP_SHOWWINDOW);\r
+\r
+    hw_firstctl = GetNextDlgTabItem(hw, NULL, FALSE);\r
+    if (hw_firstctl) {\r
+        SetFocus(hw_firstctl);\r
+    }\r
 }\r
 \r
 static INT_PTR\r
index 220865113b3b9062ef3d18c4c46b20bae561643b..ac5f930283c04a45085dd1c8c7be0bd77b0c4a4e 100644 (file)
@@ -34,6 +34,7 @@ typedef struct tag_notif_data {
 \r
     BOOL monitor;\r
     BOOL renew;\r
+    BOOL halflife;\r
     BOOL warn1;\r
     BOOL warn2;\r
 \r
@@ -59,6 +60,10 @@ read_params(notif_data * d) {
     assert(KHM_SUCCEEDED(rv));\r
     d->renew = !!t;\r
 \r
+    rv = khc_read_int32(csp_cw, L"RenewAtHalfLife", &t);\r
+    assert(KHM_SUCCEEDED(rv));\r
+    d->halflife = !!t;\r
+\r
     rv = khc_read_int32(csp_cw, L"AllowWarn", &t);\r
     assert(KHM_SUCCEEDED(rv));\r
     d->warn1 = !!t;\r
@@ -106,6 +111,7 @@ check_for_modification(notif_data * d) {
 \r
     if ((!!d->monitor) != (!!t.monitor) ||\r
         (!!d->renew) != (!!t.renew) ||\r
+        (!!d->halflife) != (!!t.halflife) ||\r
         (!!d->warn1) != (!!t.warn1) ||\r
         (!!d->warn2) != (!!t.warn2) ||\r
         d->tc_renew.current != t.tc_renew.current ||\r
@@ -144,6 +150,9 @@ write_params(notif_data * d) {
     rv = khc_write_int32(csp_cw, L"AllowAutoRenew", d->renew);\r
     assert(KHM_SUCCEEDED(rv));\r
 \r
+    rv = khc_write_int32(csp_cw, L"RenewAtHalfLife", d->halflife);\r
+    assert(KHM_SUCCEEDED(rv));\r
+\r
     rv = khc_write_int32(csp_cw, L"AllowWarn", d->warn1);\r
     assert(KHM_SUCCEEDED(rv));\r
 \r
@@ -178,6 +187,8 @@ refresh_view(HWND hwnd, notif_data * d) {
                    (d->monitor?BST_CHECKED:BST_UNCHECKED));\r
     CheckDlgButton(hwnd, IDC_NOTIF_RENEW, \r
                    (d->renew?BST_CHECKED:BST_UNCHECKED));\r
+    CheckDlgButton(hwnd, IDC_NOTIF_HALFLIFE,\r
+                   (d->halflife?BST_CHECKED:BST_UNCHECKED));\r
     CheckDlgButton(hwnd, IDC_NOTIF_WARN1, \r
                    (d->warn1?BST_CHECKED:BST_UNCHECKED));\r
     CheckDlgButton(hwnd, IDC_NOTIF_WARN2, \r
@@ -187,6 +198,7 @@ refresh_view(HWND hwnd, notif_data * d) {
     khui_tracker_refresh(&d->tc_warn2);\r
     if (!d->monitor) {\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), FALSE);\r
+        EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), FALSE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), FALSE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), FALSE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), FALSE);\r
@@ -194,6 +206,7 @@ refresh_view(HWND hwnd, notif_data * d) {
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), FALSE);\r
     } else {\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), TRUE);\r
+        EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), TRUE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), TRUE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), TRUE);\r
         EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), !!(d->renew));\r
@@ -208,6 +221,8 @@ refresh_data(HWND hwnd, notif_data * d) {
                   == BST_CHECKED);\r
     d->renew   = (IsDlgButtonChecked(hwnd, IDC_NOTIF_RENEW)\r
                   == BST_CHECKED);\r
+    d->halflife = (IsDlgButtonChecked(hwnd, IDC_NOTIF_HALFLIFE)\r
+                   == BST_CHECKED);\r
     d->warn1   = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN1)\r
                   == BST_CHECKED);\r
     d->warn2   = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN2)\r
index 6dad3698ff33c09e99243d5b49744c819ef8c844..cab71c4ea281c4d9c59e85c6ddd5364f7d907b97 100644 (file)
@@ -37,8 +37,163 @@ typedef struct tag_plugin_data {
 typedef struct tag_plugin_dlg_data {\r
     plugin_data * info[MAX_PLUGINS];\r
     khm_size n_info;\r
+\r
+    plugin_data * selected;\r
+    HICON plugin_ico;\r
 } plugin_dlg_data;\r
 \r
+void update_dialog_fields(HWND hwnd,\r
+                          plugin_dlg_data * d,\r
+                          plugin_data * info) {\r
+    wchar_t buf[256];\r
+    UINT resid;\r
+    wchar_t * t;\r
+    khm_handle csp_module = NULL;\r
+\r
+    d->selected = info;\r
+\r
+    if (info->plugin.reg.description)\r
+        SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description);\r
+    else {\r
+        wchar_t fmt[128];\r
+\r
+        LoadString(khm_hInstance, IDS_CFG_NODESC, fmt, ARRAYLENGTH(fmt));\r
+        StringCbPrintf(buf, sizeof(buf), fmt, info->plugin.reg.name);\r
+        SetDlgItemText(hwnd, IDC_CFG_DESC, buf);\r
+    }\r
+    \r
+    switch(info->plugin.state) {\r
+    case KMM_PLUGIN_STATE_FAIL_INIT:\r
+        resid = IDS_PISTATE_FAILINIT;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_FAIL_UNKNOWN:\r
+        resid = IDS_PISTATE_FAILUNK;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE:\r
+        resid = IDS_PISTATE_FAILMAX;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED:\r
+        resid = IDS_PISTATE_FAILREG;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_FAIL_DISABLED:\r
+        resid = IDS_PISTATE_FAILDIS;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_FAIL_LOAD:\r
+        resid = IDS_PISTATE_FAILLOD;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_NONE:\r
+    case KMM_PLUGIN_STATE_PLACEHOLDER:\r
+        resid = IDS_PISTATE_PLACEHOLD;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_REG:\r
+    case KMM_PLUGIN_STATE_PREINIT:\r
+        resid = IDS_PISTATE_REG;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_HOLD:\r
+        resid = IDS_PISTATE_HOLD;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_INIT:\r
+        resid = IDS_PISTATE_INIT;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_RUNNING:\r
+        resid = IDS_PISTATE_RUN;\r
+        break;\r
+\r
+    case KMM_PLUGIN_STATE_EXITED:\r
+        resid = IDS_PISTATE_EXIT;\r
+        break;\r
+\r
+    default:\r
+#ifdef DEBUG\r
+        assert(FALSE);\r
+#endif\r
+        resid = IDS_PISTATE_FAILUNK;\r
+    }\r
+\r
+    LoadString(khm_hInstance, resid,\r
+               buf, ARRAYLENGTH(buf));\r
+\r
+    SetDlgItemText(hwnd, IDC_CFG_STATE, buf);\r
+\r
+    SendDlgItemMessage(hwnd, IDC_CFG_DEPS,\r
+                       LB_RESETCONTENT, 0, 0);\r
+\r
+    for (t = info->plugin.reg.dependencies; t && *t;\r
+         t = multi_string_next(t)) {\r
+        SendDlgItemMessage(hwnd, IDC_CFG_DEPS,\r
+                           LB_INSERTSTRING, -1, (LPARAM) t);\r
+    }\r
+\r
+    if (info->plugin.reg.module)\r
+        SetDlgItemText(hwnd, IDC_CFG_MODULE,\r
+                       info->plugin.reg.module);\r
+    else\r
+        SetDlgItemText(hwnd, IDC_CFG_MODULE,\r
+                       L"");\r
+\r
+    if (info->module.reg.vendor)\r
+        SetDlgItemText(hwnd, IDC_CFG_VENDOR,\r
+                       info->module.reg.vendor);\r
+    else\r
+        SetDlgItemText(hwnd, IDC_CFG_VENDOR,\r
+                       L"");\r
+\r
+    StringCbPrintf(buf, sizeof(buf), L"%u.%u.%u.%u",\r
+                   (unsigned int) info->module.product_version.major,\r
+                   (unsigned int) info->module.product_version.minor,\r
+                   (unsigned int) info->module.product_version.patch,\r
+                   (unsigned int) info->module.product_version.aux);\r
+\r
+    SetDlgItemText(hwnd, IDC_CFG_VERSION, buf);\r
+\r
+    if (info->plugin.reg.icon) {\r
+        SendDlgItemMessage(hwnd, IDC_CFG_ICON,\r
+                           STM_SETICON,\r
+                           (WPARAM) info->plugin.reg.icon,\r
+                           0);\r
+    } else {\r
+        SendDlgItemMessage(hwnd, IDC_CFG_ICON,\r
+                           STM_SETICON,\r
+                           (WPARAM) d->plugin_ico,\r
+                           0);\r
+    }\r
+\r
+    if (KHM_SUCCEEDED(kmm_get_module_config(info->module.reg.name,\r
+                                            0, &csp_module)) &&\r
+        (khc_value_exists(csp_module, L"ImagePath") &\r
+         (KCONF_FLAG_MACHINE | KCONF_FLAG_USER))) {\r
+\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), TRUE);\r
+    } else {\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);\r
+    }\r
+\r
+    if (csp_module)\r
+        khc_close_space(csp_module);\r
+\r
+    if (info->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), TRUE);\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);\r
+    } else {\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);\r
+        EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), TRUE);\r
+    }\r
+}\r
+\r
+#define IDX_PLUGIN_NORMAL   1\r
+#define IDX_PLUGIN_DISABLED 2\r
+#define IDX_PLUGIN_ERROR    3\r
+\r
 INT_PTR CALLBACK\r
 khm_cfg_plugins_proc(HWND hwnd,\r
                      UINT uMsg,\r
@@ -58,7 +213,8 @@ khm_cfg_plugins_proc(HWND hwnd,
             RECT r;\r
             HWND hw;\r
             wchar_t buf[256];\r
-\r
+            HIMAGELIST h_ilist;\r
+            HICON h_icon;\r
 \r
             d = PMALLOC(sizeof(*d));\r
 #ifdef DEBUG\r
@@ -87,6 +243,8 @@ khm_cfg_plugins_proc(HWND hwnd,
 #ifdef DEBUG\r
                 assert(d->info[i]);\r
 #endif\r
+                ZeroMemory(&d->info[i]->plugin,\r
+                           sizeof(d->info[i]->plugin));\r
 \r
                 if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) {\r
                     PFREE(d->info[i]);\r
@@ -120,6 +278,50 @@ khm_cfg_plugins_proc(HWND hwnd,
 #ifdef DEBUG\r
             assert(hw);\r
 #endif\r
+\r
+            h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON),\r
+                                       GetSystemMetrics(SM_CYSMICON),\r
+                                       ILC_COLOR8,\r
+                                       4, 4);\r
+\r
+            h_icon = LoadImage(khm_hInstance,\r
+                               MAKEINTRESOURCE(IDI_CFG_PLUGIN),\r
+                               IMAGE_ICON,\r
+                               GetSystemMetrics(SM_CXSMICON),\r
+                               GetSystemMetrics(SM_CYSMICON),\r
+                               LR_DEFAULTCOLOR);\r
+#ifdef DEBUG\r
+            assert(h_icon);\r
+#endif\r
+            ImageList_AddIcon(h_ilist, h_icon);\r
+            DestroyIcon(h_icon);\r
+\r
+            h_icon = LoadImage(khm_hInstance,\r
+                               MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS),\r
+                               IMAGE_ICON,\r
+                               GetSystemMetrics(SM_CXSMICON),\r
+                               GetSystemMetrics(SM_CYSMICON),\r
+                               LR_DEFAULTCOLOR);\r
+#ifdef DEBUG\r
+            assert(h_icon);\r
+#endif\r
+            ImageList_AddIcon(h_ilist, h_icon);\r
+            DestroyIcon(h_icon);\r
+\r
+            h_icon = LoadImage(khm_hInstance,\r
+                               MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR),\r
+                               IMAGE_ICON,\r
+                               GetSystemMetrics(SM_CXSMICON),\r
+                               GetSystemMetrics(SM_CYSMICON),\r
+                               LR_DEFAULTCOLOR);\r
+#ifdef DEBUG\r
+            assert(h_icon);\r
+#endif\r
+            ImageList_AddIcon(h_ilist, h_icon);\r
+            DestroyIcon(h_icon);\r
+\r
+            ListView_SetImageList(hw, h_ilist, LVSIL_STATE);\r
+\r
             ZeroMemory(&lvc, sizeof(lvc));\r
 \r
             lvc.mask = LVCF_TEXT | LVCF_WIDTH;\r
@@ -137,12 +339,28 @@ khm_cfg_plugins_proc(HWND hwnd,
 \r
                 ZeroMemory(&lvi, sizeof(lvi));\r
 \r
-                lvi.mask = LVIF_PARAM | LVIF_TEXT;\r
+                lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;\r
                 lvi.lParam = (LPARAM) d->info[i];\r
                 lvi.pszText = d->info[i]->plugin.reg.name;\r
 \r
+                if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) {\r
+                    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED);\r
+                } else if (d->info[i]->plugin.state < 0) {\r
+                    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR);\r
+                } else {\r
+                    lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL);\r
+                }\r
+\r
                 ListView_InsertItem(hw, &lvi);\r
             }\r
+\r
+            d->plugin_ico =\r
+                (HICON) LoadImage(khm_hInstance,\r
+                                  MAKEINTRESOURCE(IDI_CFG_PLUGIN),\r
+                                  IMAGE_ICON,\r
+                                  GetSystemMetrics(SM_CXICON),\r
+                                  GetSystemMetrics(SM_CYICON),\r
+                                  LR_DEFAULTCOLOR);\r
         }\r
         return FALSE;\r
 \r
@@ -169,16 +387,18 @@ khm_cfg_plugins_proc(HWND hwnd,
                     SetDlgItemText(hwnd, IDC_CFG_STATE, L"");\r
                     SetDlgItemText(hwnd, IDC_CFG_MODULE, L"");\r
                     SetDlgItemText(hwnd, IDC_CFG_VENDOR, L"");\r
+                    SetDlgItemText(hwnd, IDC_CFG_VERSION, L"");\r
                     EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE);\r
                     EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE);\r
+                    EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE);\r
                     SendDlgItemMessage(hwnd, IDC_CFG_DEPS, \r
                                        LB_RESETCONTENT, 0, 0);\r
+                    SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON,\r
+                                       (WPARAM) d->plugin_ico, 0);\r
+                    d->selected = NULL;\r
                 } else {\r
                     int idx;\r
                     plugin_data * info;\r
-                    wchar_t buf[256];\r
-                    UINT resid;\r
-                    wchar_t * t;\r
 \r
                     idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED);\r
 #ifdef DEBUG\r
@@ -195,95 +415,205 @@ khm_cfg_plugins_proc(HWND hwnd,
 #endif\r
                     info = (plugin_data *) lvi.lParam;\r
 \r
-                    if (info->plugin.reg.description)\r
-                        SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description);\r
-                    else\r
-                        SetDlgItemText(hwnd, IDC_CFG_DESC, L"");\r
+                    update_dialog_fields(hwnd, d, info);\r
+                }\r
+            }\r
+        }\r
+        return TRUE;\r
 \r
-                    switch(info->plugin.state) {\r
-                    case KMM_PLUGIN_STATE_FAIL_UNKNOWN:\r
-                        resid = IDS_PISTATE_FAILUNK;\r
-                        break;\r
+    case WM_COMMAND:\r
+        {\r
 \r
-                    case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE:\r
-                        resid = IDS_PISTATE_FAILMAX;\r
-                        break;\r
+            d = (plugin_dlg_data *) (LONG_PTR)\r
+                GetWindowLongPtr(hwnd, DWLP_USER);\r
 \r
-                    case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED:\r
-                        resid = IDS_PISTATE_FAILREG;\r
-                        break;\r
+            switch (wParam) {\r
+            case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED):\r
+                if (d->selected != NULL) {\r
+                    khui_alert * alert = NULL;\r
+                    wchar_t buf[KHUI_MAXCCH_MESSAGE];\r
+                    wchar_t fmt[KHUI_MAXCCH_MESSAGE];\r
+                    kmm_plugin p;\r
 \r
-                    case KMM_PLUGIN_STATE_FAIL_DISABLED:\r
-                        resid = IDS_PISTATE_FAILDIS;\r
-                        break;\r
+                    khui_alert_create_empty(&alert);\r
 \r
-                    case KMM_PLUGIN_STATE_FAIL_LOAD:\r
-                        resid = IDS_PISTATE_FAILLOD;\r
-                        break;\r
+                    LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);\r
+                    khui_alert_set_title(alert, buf);\r
 \r
-                    case KMM_PLUGIN_STATE_NONE:\r
-                    case KMM_PLUGIN_STATE_PLACEHOLDER:\r
-                        resid = IDS_PISTATE_PLACEHOLD;\r
-                        break;\r
+                    LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);\r
+                    khui_alert_set_message(alert, buf);\r
 \r
-                    case KMM_PLUGIN_STATE_REG:\r
-                    case KMM_PLUGIN_STATE_PREINIT:\r
-                        resid = IDS_PISTATE_REG;\r
-                        break;\r
+                    khui_alert_set_severity(alert, KHERR_INFO);\r
 \r
-                    case KMM_PLUGIN_STATE_HOLD:\r
-                        resid = IDS_PISTATE_HOLD;\r
-                        break;\r
+                    khui_alert_show_modal(alert);\r
 \r
-                    case KMM_PLUGIN_STATE_INIT:\r
-                        resid = IDS_PISTATE_INIT;\r
-                        break;\r
+                    kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE);\r
 \r
-                    case KMM_PLUGIN_STATE_RUNNING:\r
-                        resid = IDS_PISTATE_RUN;\r
-                        break;\r
+                    khui_alert_release(alert);\r
+\r
+                    p = d->selected->plugin.h_plugin;\r
+                    kmm_hold_plugin(p);\r
+                    kmm_release_plugin_info_i(&d->selected->plugin);\r
+                    kmm_get_plugin_info_i(p, &d->selected->plugin);\r
+                    kmm_release_plugin(p);\r
 \r
-                    case KMM_PLUGIN_STATE_EXITED:\r
-                        resid = IDS_PISTATE_EXIT;\r
+                    update_dialog_fields(hwnd, d, d->selected);\r
+                }\r
+                break;\r
+\r
+            case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED):\r
+                if (d->selected != NULL) {\r
+                    khui_alert * alert = NULL;\r
+                    wchar_t buf[KHUI_MAXCCH_MESSAGE];\r
+                    wchar_t fmt[KHUI_MAXCCH_MESSAGE];\r
+                    wchar_t depends[KHUI_MAXCCH_MESSAGE];\r
+                    khm_size i;\r
+                    kmm_plugin p;\r
+\r
+                    khui_alert_create_empty(&alert);\r
+#ifdef DEBUG\r
+                    assert(alert);\r
+#endif\r
+                    if (alert == NULL)\r
                         break;\r
 \r
-                    default:\r
+                    LoadString(khm_hInstance, IDS_CFG_P_DELCNFT,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);\r
+                    khui_alert_set_title(alert, buf);\r
+\r
+                    LoadString(khm_hInstance, IDS_CFG_P_DELCNFM,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name);\r
+                    khui_alert_set_message(alert, buf);\r
+\r
+                    depends[0] = L'\0';\r
+\r
+                    for (i=0; i<d->n_info; i++) {\r
+                        wchar_t * t;\r
+\r
+                        t = d->info[i]->plugin.reg.dependencies;\r
+\r
+                        while(t) {\r
+                            if (!wcscmp(t, d->selected->plugin.reg.name)) {\r
+                                if (depends[0])\r
+                                    StringCbCat(depends, sizeof(depends), L", ");\r
+                                StringCbCat(depends, sizeof(depends),\r
+                                            d->info[i]->plugin.reg.name);\r
+                                break;\r
+                            }\r
+                            t = multi_string_next(t);\r
+                        }\r
+                    }\r
+\r
+                    if (depends[0]) {\r
+                        LoadString(khm_hInstance, IDS_CFG_P_DELCNFS,\r
+                                   fmt, ARRAYLENGTH(fmt));\r
+                        StringCbPrintf(buf, sizeof(buf), fmt, depends);\r
+                        khui_alert_set_suggestion(alert, buf);\r
+                    } else {\r
+                        LoadString(khm_hInstance, IDS_CFG_P_DELNDEP,\r
+                                   buf, ARRAYLENGTH(buf));\r
+                        khui_alert_set_suggestion(alert, buf);\r
+                    }\r
+\r
+                    khui_alert_add_command(alert, KHUI_PACTION_YES);\r
+                    khui_alert_add_command(alert, KHUI_PACTION_NO);\r
+\r
+                    khui_alert_set_severity(alert, KHERR_WARNING);\r
+\r
+                    if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&\r
+                        alert->response == KHUI_PACTION_YES) {\r
+                        kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE);\r
+                    }\r
+\r
+                    khui_alert_release(alert);\r
+\r
+                    p = d->selected->plugin.h_plugin;\r
+                    kmm_hold_plugin(p);\r
+                    kmm_release_plugin_info_i(&d->selected->plugin);\r
+                    kmm_get_plugin_info_i(p, &d->selected->plugin);\r
+                    kmm_release_plugin(p);\r
+\r
+                    update_dialog_fields(hwnd, d, d->selected);\r
+                }\r
+                break;\r
+\r
+            case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED):\r
+                {\r
+                    khui_alert * alert = NULL;\r
+                    wchar_t buf[KHUI_MAXCCH_MESSAGE];\r
+                    wchar_t fmt[KHUI_MAXCCH_MESSAGE];\r
+                    wchar_t plist[KHUI_MAXCCH_MESSAGE];\r
+                    khm_size i;\r
+\r
+                    if (d->selected == NULL) {\r
 #ifdef DEBUG\r
                         assert(FALSE);\r
 #endif\r
-                        resid = IDS_PISTATE_FAILUNK;\r
+                        break;\r
                     }\r
 \r
-                    LoadString(khm_hInstance, resid,\r
-                               buf, ARRAYLENGTH(buf));\r
+                    khui_alert_create_empty(&alert);\r
 \r
-                    SetDlgItemText(hwnd, IDC_CFG_STATE, buf);\r
+                    LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt,\r
+                                   d->selected->plugin.reg.name);\r
 \r
-                    SendDlgItemMessage(hwnd, IDC_CFG_DEPS,\r
-                                       LB_RESETCONTENT, 0, 0);\r
+                    khui_alert_set_title(alert, buf);\r
+\r
+                    LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt,\r
+                                   d->selected->plugin.reg.name);\r
+\r
+                    khui_alert_set_message(alert, buf);\r
 \r
-                    for (t = info->plugin.reg.dependencies; t && *t;\r
-                         t = multi_string_next(t)) {\r
-                        SendDlgItemMessage(hwnd, IDC_CFG_DEPS,\r
-                                           LB_INSERTSTRING,\r
-                                           -1,\r
-                                           (LPARAM) t);\r
+                    plist[0] = L'\0';\r
+                    for (i=0; i < d->n_info; i++) {\r
+                        if (!wcscmp(d->info[i]->module.reg.name,\r
+                                    d->selected->module.reg.name)) {\r
+                            if (plist[0])\r
+                                StringCbCat(plist, sizeof(plist), L", ");\r
+                            StringCbCat(plist, sizeof(plist),\r
+                                        d->info[i]->plugin.reg.name);\r
+                        }\r
                     }\r
 \r
-                    if (info->plugin.reg.module)\r
-                        SetDlgItemText(hwnd, IDC_CFG_MODULE,\r
-                                       info->plugin.reg.module);\r
-                    else\r
-                        SetDlgItemText(hwnd, IDC_CFG_MODULE,\r
-                                       L"");\r
-\r
-                    if (info->module.reg.vendor)\r
-                        SetDlgItemText(hwnd, IDC_CFG_VENDOR,\r
-                                       info->module.reg.vendor);\r
-                    else\r
-                        SetDlgItemText(hwnd, IDC_CFG_VENDOR,\r
-                                       L"");\r
+#ifdef DEBUG\r
+                    /* there should have been at least one plugin */\r
+                    assert(plist[0]);\r
+#endif\r
+\r
+                    LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS,\r
+                               fmt, ARRAYLENGTH(fmt));\r
+                    StringCbPrintf(buf, sizeof(buf), fmt, plist);\r
+                    khui_alert_set_suggestion(alert, buf);\r
+\r
+                    khui_alert_add_command(alert, KHUI_PACTION_YES);\r
+                    khui_alert_add_command(alert, KHUI_PACTION_NO);\r
+\r
+                    khui_alert_set_severity(alert, KHERR_WARNING);\r
+\r
+                    if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) &&\r
+                        alert->response == KHUI_PACTION_YES) {\r
+                        kmm_unregister_module(d->selected->module.reg.name, 0);\r
+\r
+                        update_dialog_fields(hwnd, d, d->selected);\r
+                    }\r
+                }\r
+                break;\r
+\r
+            case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED):\r
+                {\r
+                    \r
                 }\r
+                break;\r
             }\r
         }\r
         return TRUE;\r
index 7441b54f885f7c366a25a822a41abfdd40a4b1b2..63ec2d5fed70ce7c84e9843e9cc78c6da6817a44 100644 (file)
@@ -450,10 +450,8 @@ cfgui_update_state(HWND hwnd,
     TreeView_SetItem(hwtv, &itx);\r
 \r
     if(cfgui_check_mod_state(NULL)) {\r
-        EnableWindow(GetDlgItem(hwnd, IDC_CFG_SUMMARY), TRUE);\r
         EnableWindow(GetDlgItem(hwnd, IDAPPLY), TRUE);\r
     } else {\r
-        EnableWindow(GetDlgItem(hwnd, IDC_CFG_SUMMARY), FALSE);\r
         EnableWindow(GetDlgItem(hwnd, IDAPPLY), FALSE);\r
     }\r
 }\r
@@ -512,7 +510,7 @@ cfgui_dlgproc_generic(HWND hwnd,
             r_fill.bottom = r_logo.top;\r
             FillRect(hdc, &r_fill, d->hbr_white);\r
 \r
-            SetWindowLong(hwnd, DWL_MSGRESULT, (LONG) TRUE);\r
+            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG) TRUE);\r
         }\r
         return TRUE;\r
     }\r
@@ -591,6 +589,8 @@ cfgui_dlgproc(HWND hwnd,
         {\r
             LPNMHDR lpnm;\r
             LPNMTREEVIEW lptv;\r
+            LPNMTVGETINFOTIP lpgi;\r
+            khui_config_node node;\r
 \r
             lpnm = (LPNMHDR) lParam;\r
 \r
@@ -601,6 +601,31 @@ cfgui_dlgproc(HWND hwnd,
                                     (khui_config_node) \r
                                     lptv->itemNew.lParam);\r
                 return TRUE;\r
+\r
+            case TVN_GETINFOTIP:\r
+                lpgi = (LPNMTVGETINFOTIP) lParam;\r
+                node = (khui_config_node) lpgi->lParam;\r
+\r
+                if (node) {\r
+                    khm_int32 flags = 0;\r
+\r
+                    flags = khui_cfg_get_flags(node);\r
+\r
+                    if (flags & KHUI_CNFLAG_MODIFIED) {\r
+                        LoadString(khm_hInstance, IDS_CFG_IT_MOD,\r
+                                   lpgi->pszText, lpgi->cchTextMax);\r
+                    } else if (flags & KHUI_CNFLAG_APPLIED) {\r
+                        LoadString(khm_hInstance, IDS_CFG_IT_APP,\r
+                                   lpgi->pszText, lpgi->cchTextMax);\r
+                    } else {\r
+                        LoadString(khm_hInstance, IDS_CFG_IT_NONE,\r
+                                   lpgi->pszText, lpgi->cchTextMax);\r
+                    }\r
+                } else {\r
+                    StringCchCopy(lpgi->pszText, lpgi->cchTextMax, L"");\r
+                }\r
+\r
+                return TRUE;\r
             }\r
         }\r
         return TRUE;\r
@@ -691,6 +716,9 @@ void khm_refresh_config(void) {
     khm_int32 rv;\r
     int n_tries = 0;\r
     khui_config_node cfg_ids = NULL;\r
+    khui_config_node cfg_r = NULL;\r
+    khui_menu_def * omenu;\r
+    khm_boolean refresh_menu = FALSE;\r
 \r
     do {\r
         rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,\r
@@ -766,10 +794,81 @@ void khm_refresh_config(void) {
         }\r
     }\r
 \r
+    /* Now iterate through the root level configuration nodes and make\r
+       sure we have a menu item for each of them. */\r
+    if (KHM_FAILED(khui_cfg_get_first_child(NULL, &cfg_r)))\r
+        goto _cleanup;\r
+\r
+    omenu = khui_find_menu(KHUI_MENU_OPTIONS);\r
+    if (omenu == NULL)\r
+        goto _cleanup;\r
+\r
+    do {\r
+        khm_int32 action;\r
+        khm_int32 flags;\r
+        khui_action * paction;\r
+        wchar_t cname[KHUI_MAXCCH_NAME];\r
+        wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];\r
+        khm_size cb;\r
+        khm_handle sub;\r
+        khui_config_node_reg reg;\r
+\r
+        flags = khui_cfg_get_flags(cfg_r);\r
+        if (flags & KHUI_CNFLAG_SYSTEM)\r
+            goto _next_cfg;\r
+\r
+        cb = sizeof(cname);\r
+        if (KHM_FAILED(khui_cfg_get_name(cfg_r, cname, &cb))) {\r
+#ifdef DEBUG\r
+            assert(FALSE);\r
+#endif\r
+            goto _next_cfg;\r
+        }\r
+\r
+        paction = khui_find_named_action(cname);\r
+\r
+        if (!paction) {\r
+            khui_cfg_get_reg(cfg_r, &reg);\r
+\r
+            kmq_create_hwnd_subscription(khm_hwnd_main, &sub);\r
+\r
+            StringCbCopy(wshort, sizeof(wshort), reg.short_desc);\r
+            StringCbCat(wshort, sizeof(wshort), L" ...");\r
+\r
+            action = khui_action_create(cname,\r
+                                        wshort,\r
+                                        reg.long_desc,\r
+                                        (void *) CFGACTION_MAGIC,\r
+                                        KHUI_ACTIONTYPE_TRIGGER,\r
+                                        sub);\r
+\r
+            if (action == 0) {\r
+#ifdef DEBUG\r
+                assert(FALSE);\r
+#endif\r
+                goto _next_cfg;\r
+            }\r
+\r
+            khui_menu_insert_action(omenu, -1, action, 0);\r
+\r
+            refresh_menu = TRUE;\r
+        }\r
+\r
+    _next_cfg:\r
+        if (KHM_FAILED(khui_cfg_get_next_release(&cfg_r)))\r
+            break;\r
+    } while(cfg_r);\r
+\r
+    if (refresh_menu)\r
+        khm_menu_refresh_items();\r
+\r
  _cleanup:\r
     if (cfg_ids)\r
         khui_cfg_release(cfg_ids);\r
 \r
+    if (cfg_r)\r
+        khui_cfg_release(cfg_r);\r
+\r
     if (idents)\r
         PFREE(idents);\r
 }\r
@@ -783,7 +882,7 @@ void khm_init_config(void) {
     reg.short_desc = wshort;\r
     reg.long_desc = wlong;\r
     reg.h_module = khm_hInstance;\r
-    reg.flags = 0;\r
+    reg.flags = KHUI_CNFLAG_SYSTEM;\r
 \r
     reg.name = L"KhmGeneral";\r
     reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_GENERAL);\r
@@ -818,7 +917,7 @@ void khm_init_config(void) {
                wshort, ARRAYLENGTH(wshort));\r
     LoadString(khm_hInstance, IDS_CFG_IDS_TAB_LONG,\r
                wlong, ARRAYLENGTH(wlong));\r
-    reg.flags = KHUI_CNFLAG_SUBPANEL;\r
+    reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;\r
 \r
     khui_cfg_register(node, &reg);\r
 \r
@@ -829,11 +928,11 @@ void khm_init_config(void) {
                wshort, ARRAYLENGTH(wshort));\r
     LoadString(khm_hInstance, IDS_CFG_ID_TAB_LONG,\r
                wlong, ARRAYLENGTH(wlong));\r
-    reg.flags = KHUI_CNFLAG_PLURAL | KHUI_CNFLAG_SUBPANEL;\r
+    reg.flags = KHUI_CNFLAG_PLURAL | KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM;\r
 \r
     khui_cfg_register(node, &reg);\r
 \r
-    reg.flags = 0;\r
+    reg.flags = KHUI_CNFLAG_SYSTEM;\r
     khui_cfg_release(node);\r
 \r
     reg.name = L"KhmNotifications";\r
index 62747fcad153e919fb1bc4ea5f46a76c6bb4446b..61db340c896b4840f520ca7eeb542800a7533223 100644 (file)
@@ -27,6 +27,8 @@
 #ifndef __KHIMAIRA_CONFIGWND_H\r
 #define __KHIMAIRA_CONFIGWND_H\r
 \r
+#define CFGACTION_MAGIC 0x38f8\r
+\r
 void \r
 khm_show_config_pane(khui_config_node node);\r
 \r
index 7e0756fb45cdc5eafb74b09ff9fbca116d58b1fe..e09791e7be2ae477ef8cf6fa4adae30a3dc03bc2 100644 (file)
@@ -380,7 +380,7 @@ void khm_cred_set_default(void)
     khui_context_release(&ctx);\r
 }\r
 \r
-void khm_cred_destroy_creds(void)\r
+void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet)\r
 {\r
     khui_action_context * pctx;\r
 \r
@@ -391,7 +391,7 @@ void khm_cred_destroy_creds(void)
 \r
     khui_context_get(pctx);\r
 \r
-    if(pctx->scope == KHUI_SCOPE_NONE) {\r
+    if(pctx->scope == KHUI_SCOPE_NONE && !quiet) {\r
         /* this really shouldn't be necessary once we start enabling\r
            and disbling actions based on context */\r
         wchar_t title[256];\r
@@ -413,18 +413,26 @@ void khm_cred_destroy_creds(void)
 \r
         khui_context_release(pctx);\r
         PFREE(pctx);\r
-    } else {\r
-        _begin_task(KHERR_CF_TRANSITIVE);\r
-        _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS);\r
-        _describe();\r
 \r
+        return;\r
+    }\r
+\r
+    _begin_task(KHERR_CF_TRANSITIVE);\r
+    _report_sr0(KHERR_NONE, IDS_CTX_DESTROY_CREDS);\r
+    _describe();\r
+\r
+    if (sync)\r
+        kmq_send_message(KMSG_CRED,\r
+                         KMSG_CRED_DESTROY_CREDS,\r
+                         0,\r
+                         (void *) pctx);\r
+    else\r
         kmq_post_message(KMSG_CRED,\r
                          KMSG_CRED_DESTROY_CREDS,\r
                          0,\r
                          (void *) pctx);\r
 \r
-        _end_task();\r
-    }\r
+    _end_task();\r
 }\r
 \r
 void khm_cred_renew_identity(khm_handle identity)\r
@@ -434,7 +442,7 @@ void khm_cred_renew_identity(khm_handle identity)
     khui_cw_create_cred_blob(&c);\r
 \r
     c->subtype = KMSG_CRED_RENEW_CREDS;\r
-    c->result = KHUI_NC_RESULT_GET_CREDS;\r
+    c->result = KHUI_NC_RESULT_PROCESS;\r
     khui_context_create(&c->ctx,\r
                         KHUI_SCOPE_IDENT,\r
                         identity,\r
@@ -457,7 +465,7 @@ void khm_cred_renew_cred(khm_handle cred)
     khui_cw_create_cred_blob(&c);\r
 \r
     c->subtype = KMSG_CRED_RENEW_CREDS;\r
-    c->result = KHUI_NC_RESULT_GET_CREDS;\r
+    c->result = KHUI_NC_RESULT_PROCESS;\r
     khui_context_create(&c->ctx,\r
                         KHUI_SCOPE_CRED,\r
                         NULL,\r
@@ -479,7 +487,7 @@ void khm_cred_renew_creds(void)
 \r
     khui_cw_create_cred_blob(&c);\r
     c->subtype = KMSG_CRED_RENEW_CREDS;\r
-    c->result = KHUI_NC_RESULT_GET_CREDS;\r
+    c->result = KHUI_NC_RESULT_PROCESS;\r
     khui_context_get(&c->ctx);\r
 \r
     _begin_task(KHERR_CF_TRANSITIVE);\r
@@ -855,7 +863,7 @@ khm_cred_process_commandline(void) {
                                  NULL, NULL, 0,\r
                                  NULL);\r
 \r
-                khm_cred_destroy_creds();\r
+                khm_cred_destroy_creds(FALSE, FALSE);\r
             }\r
 \r
             khm_startup.destroy = FALSE;\r
index b9be3d4875b0e0554097aa8032a85c50aa9501c1..fe8ed6c2570584a3c3b7042692640fc6228cdef3 100644 (file)
@@ -31,7 +31,8 @@ void KHMAPI
 kmsg_cred_completion(kmq_message *m);\r
 \r
 void \r
-khm_cred_destroy_creds(void);\r
+khm_cred_destroy_creds(khm_boolean sync,\r
+                       khm_boolean quiet);\r
 \r
 void \r
 khm_cred_renew_identity(khm_handle identity);\r
index 5211d50b164ae688ce90b31ae92734f1f27420ee..1d5d6643e1df6bf6faa7d5d92803de4adfc6043b 100644 (file)
 ATOM khui_credwnd_cls;\r
 khm_int32 khui_cw_flag_id;\r
 \r
+khm_int32 attr_to_action[KCDB_ATTR_MAX_ID + 1];\r
+\r
+void\r
+cw_refresh_attribs(HWND hwnd) {\r
+    khm_int32 act;\r
+    kcdb_attrib * attrib;\r
+    khui_menu_def * menu;\r
+    khm_int32 i;\r
+\r
+    menu = khui_find_menu(KHUI_MENU_COLUMNS);\r
+#ifdef DEBUG\r
+    assert(menu);\r
+#endif\r
+\r
+    for (i=0; i <= KCDB_ATTR_MAX_ID; i++) {\r
+        if (KHM_FAILED(kcdb_attrib_get_info(i, &attrib))) {\r
+            if (attr_to_action[i] != 0) {\r
+                /* the action should be removed */\r
+                khui_menu_remove_action(menu, attr_to_action[i]);\r
+                khui_action_delete(attr_to_action[i]);\r
+                attr_to_action[i] = 0;\r
+            }\r
+        } else {\r
+            if (attr_to_action[i] == 0 &&\r
+                !(attrib->flags & KCDB_ATTR_FLAG_HIDDEN) &&\r
+                (attrib->short_desc || attrib->long_desc)) {\r
+                /* new action */\r
+                khm_handle sub = NULL;\r
+\r
+                kmq_create_hwnd_subscription(hwnd, &sub);\r
+\r
+                act = khui_action_create(attrib->name,\r
+                                         (attrib->short_desc?\r
+                                          attrib->short_desc: attrib->long_desc),\r
+                                         NULL,\r
+                                         (void *)(UINT_PTR) i,\r
+                                         KHUI_ACTIONTYPE_TOGGLE,\r
+                                         sub);\r
+\r
+                attr_to_action[i] = act;\r
+\r
+                khui_menu_insert_action(menu, 5000, act, 0);\r
+            }\r
+\r
+            kcdb_attrib_release_info(attrib);\r
+        }\r
+    }\r
+}\r
+\r
 khm_int32 \r
 cw_get_custom_attr_id(wchar_t * s)\r
 {\r
@@ -41,6 +90,142 @@ cw_get_custom_attr_id(wchar_t * s)
     return 0;\r
 }\r
 \r
+const wchar_t *\r
+cw_get_custom_attr_string(khm_int32 attr_id)\r
+{\r
+    if (attr_id == CW_CA_FLAGS)\r
+        return CW_CANAME_FLAGS;\r
+    if (attr_id == CW_CA_TYPEICON)\r
+        return CW_CANAME_TYPEICON;\r
+    return NULL;\r
+}\r
+\r
+void\r
+cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) {\r
+    wchar_t * col_list = NULL;\r
+    khm_size cb_col_list;\r
+    khm_handle csp_cw = NULL;\r
+    khm_handle csp_views = NULL;\r
+    khm_handle csp_view = NULL;\r
+    khm_handle csp_cols = NULL;\r
+    khm_size cb;\r
+    int i;\r
+\r
+    if (tbl->n_cols == 0)\r
+        return;\r
+\r
+    cb_col_list = (KCONF_MAXCB_NAME + 1) * tbl->n_cols;\r
+\r
+    col_list = PMALLOC(cb_col_list);\r
+#ifdef DEBUG\r
+    assert(col_list);\r
+#endif\r
+\r
+    if (!col_list)\r
+        goto _cleanup;\r
+\r
+    multi_string_init(col_list, cb_col_list);\r
+\r
+    if (!view_name && (tbl->flags & KHUI_CW_TBL_CUSTVIEW)) {\r
+        view_name = L"Custom_0";\r
+    }\r
+\r
+    if (view_name) {\r
+        if (KHM_FAILED(khc_open_space(NULL, L"CredWindow",\r
+                                      KHM_PERM_READ | KHM_PERM_WRITE, &csp_cw)))\r
+            goto _cleanup;\r
+\r
+        if (KHM_FAILED(khc_open_space(csp_cw, L"Views", KHM_PERM_READ, &csp_views)))\r
+            goto _cleanup;\r
+\r
+        if (KHM_FAILED(khc_open_space(csp_views, view_name,\r
+                                      KHM_PERM_WRITE | KHM_FLAG_CREATE,\r
+                                      &csp_view)))\r
+            goto _cleanup;\r
+\r
+        /* if we are switching to a custom view, then we should mark\r
+           that as the default. */\r
+        if (tbl->flags & KHUI_CW_TBL_CUSTVIEW) {\r
+            khc_write_string(csp_cw, L"DefaultView", L"Custom_0");\r
+        }\r
+\r
+    } else {\r
+        csp_view = tbl->csp_view;\r
+    }\r
+\r
+    if (!csp_view)\r
+        goto _cleanup;\r
+\r
+    if (KHM_FAILED(khc_open_space(csp_view, L"Columns",\r
+                                  KHM_PERM_WRITE | KHM_FLAG_CREATE,\r
+                                  &csp_cols)))\r
+        goto _cleanup;\r
+\r
+    for (i=0; i < tbl->n_cols; i++) {\r
+        const wchar_t * attr_name;\r
+        kcdb_attrib * attrib = NULL;\r
+        khm_handle csp_col = NULL;\r
+\r
+        if (tbl->cols[i].attr_id < 0) {\r
+            attr_name = cw_get_custom_attr_string(tbl->cols[i].attr_id);\r
+        } else {\r
+            if (KHM_FAILED(kcdb_attrib_get_info(tbl->cols[i].attr_id,\r
+                                                &attrib))) {\r
+#ifdef DEBUG\r
+                assert(FALSE);\r
+#endif\r
+                goto _clean_col;\r
+            }\r
+\r
+            attr_name = attrib->name;\r
+        }\r
+#ifdef DEBUG\r
+        assert(attr_name);\r
+#endif\r
+\r
+        cb = cb_col_list;\r
+        multi_string_append(col_list, &cb, attr_name);\r
+\r
+        if (KHM_FAILED(khc_open_space(csp_cols, attr_name,\r
+                                      KHM_PERM_WRITE | KHM_FLAG_CREATE,\r
+                                      &csp_col)))\r
+            goto _clean_col;\r
+\r
+        khc_write_int32(csp_col, L"Width", tbl->cols[i].width);\r
+        khc_write_int32(csp_col, L"SortIndex", tbl->cols[i].sort_index);\r
+        khc_write_int32(csp_col, L"Flags", tbl->cols[i].flags);\r
+\r
+    _clean_col:\r
+\r
+        if (csp_col)\r
+            khc_close_space(csp_col);\r
+\r
+        if (attrib)\r
+            kcdb_attrib_release_info(attrib);\r
+    }\r
+\r
+    khc_write_multi_string(csp_view, L"ColumnList", col_list);\r
+\r
+ _cleanup:\r
+\r
+    if (view_name) {\r
+        if (csp_view)\r
+            khc_close_space(csp_view);\r
+\r
+        if (csp_views)\r
+            khc_close_space(csp_views);\r
+\r
+        if (csp_cw)\r
+            khc_close_space(csp_cw);\r
+    }\r
+\r
+    if (csp_cols)\r
+        khc_close_space(csp_cols);\r
+\r
+    if (col_list)\r
+        PFREE(col_list);\r
+}\r
+\r
 void \r
 cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {\r
     khm_handle hc_cw = NULL;\r
@@ -58,7 +243,8 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
 \r
     tbl->hwnd = hwnd;\r
 \r
-    if(KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, &hc_cw)))\r
+    if(KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ | KHM_PERM_WRITE,\r
+                                 &hc_cw)))\r
         return;\r
 \r
     if(KHM_FAILED(khc_open_space(hc_cw, L"Views", KHM_PERM_READ, &hc_vs)))\r
@@ -69,11 +255,33 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
         if(KHM_FAILED(khc_read_string(hc_cw, L"DefaultView", buf, &cbsize)))\r
             goto _exit;\r
         view = buf;\r
+\r
+        /* in addition, if we are loading the default view, we should\r
+           also check the appropriate menu item */\r
+\r
+        if (!wcscmp(view, L"ByIdentity"))\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),\r
+                                    KHUI_ACTION_LAYOUT_ID);\r
+        else if (!wcscmp(view, L"ByLocation"))\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),\r
+                                    KHUI_ACTION_LAYOUT_LOC);\r
+        else if (!wcscmp(view, L"ByType"))\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),\r
+                                    KHUI_ACTION_LAYOUT_TYPE);\r
+        else if (!wcscmp(view, L"Custom_0"))\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),\r
+                                    KHUI_ACTION_LAYOUT_CUST);\r
+\r
+        kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);                                \r
+    } else {\r
+        khc_write_string(hc_cw, L"DefaultView", view);\r
     }\r
 \r
     if(KHM_FAILED(khc_open_space(hc_vs, view, KHM_PERM_READ, &hc_v)))\r
         goto _exit;\r
 \r
+    tbl->csp_view = hc_v;\r
+\r
     if(KHM_FAILED(khc_open_space(hc_v, L"Columns", KHM_PERM_READ, &hc_cs)))\r
         goto _exit;\r
 \r
@@ -88,10 +296,13 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
         goto _exit;\r
 \r
     tbl->n_cols = (int) multi_string_length_n(clist);\r
-    tbl->n_total_cols = UBOUNDSS(tbl->n_cols, KHUI_CW_COL_INITIAL, KHUI_CW_COL_INCREMENT);\r
+    tbl->n_total_cols = UBOUNDSS(tbl->n_cols,\r
+                                 KHUI_CW_COL_INITIAL, KHUI_CW_COL_INCREMENT);\r
     tbl->cols = PMALLOC(sizeof(khui_credwnd_col) * tbl->n_total_cols);\r
     ZeroMemory(tbl->cols, sizeof(khui_credwnd_col) * tbl->n_total_cols);\r
 \r
+    tbl->flags &= ~(KHUI_CW_TBL_CUSTVIEW | KHUI_CW_TBL_COLSKIP);\r
+\r
     iter = clist;\r
     i = 0;\r
     while(iter) {\r
@@ -100,13 +311,27 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
         attr_id = cw_get_custom_attr_id(iter);\r
         if(!attr_id) {\r
             /* a KCDB attribute */\r
-            if(KHM_FAILED(kcdb_attrib_get_id(iter, &attr_id)))\r
+            if(KHM_FAILED(kcdb_attrib_get_id(iter, &attr_id))) {\r
+                tbl->flags |= KHUI_CW_TBL_COLSKIP;\r
                 goto _skip_col;\r
-            if(kcdb_attrib_describe(attr_id, NULL, &cbsize, KCDB_TS_SHORT) != KHM_ERROR_TOO_LONG ||\r
-                cbsize == 0)\r
+            }\r
+\r
+            if(kcdb_attrib_describe(attr_id, NULL,\r
+                                    &cbsize, KCDB_TS_SHORT) != KHM_ERROR_TOO_LONG ||\r
+               cbsize == 0) {\r
+                tbl->flags |= KHUI_CW_TBL_COLSKIP;\r
                 goto _skip_col;\r
+            }\r
+\r
             tbl->cols[i].title = PMALLOC(cbsize);\r
             kcdb_attrib_describe(attr_id, tbl->cols[i].title, &cbsize, KCDB_TS_SHORT);\r
+\r
+            if (attr_id >= 0 &&\r
+                attr_id <= KCDB_ATTR_MAX_ID &&\r
+                attr_to_action[attr_id]) {\r
+                khui_check_action(attr_to_action[attr_id], TRUE);\r
+            }\r
+\r
         } else {\r
             /* All current custom attributes are represented by icons,\r
                not names */\r
@@ -119,8 +344,9 @@ cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) {
             if(KHM_FAILED(khc_read_int32(hc_c, L"Flags", &(tbl->cols[i].flags))))\r
                 tbl->cols[i].flags = 0;\r
             if(KHM_FAILED(khc_read_int32(hc_c, L"Width", &(tbl->cols[i].width))))\r
-                tbl->cols[i].width = -1;\r
-            if(KHM_FAILED(khc_read_int32(hc_c, L"SortIndex", &(tbl->cols[i].sort_index))))\r
+                tbl->cols[i].width = 100;\r
+            if(KHM_FAILED(khc_read_int32(hc_c, L"SortIndex",\r
+                                         &(tbl->cols[i].sort_index))))\r
                 tbl->cols[i].sort_index = -1;\r
             khc_close_space(hc_c);\r
             hc_c = NULL;\r
@@ -134,6 +360,9 @@ _skip_col:
         iter = multi_string_next(iter);\r
     }\r
 \r
+    /* refresh the menus since we checked a few items */\r
+    kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
+\r
     /* adjust the number of columns.  We may have skipped columns due to\r
        inconsistencies above */\r
     tbl->n_cols = i;\r
@@ -148,8 +377,10 @@ _skip_col:
         khc_read_int32(hc_cw, L"PaddingHeader", &(tbl->hpad_h));\r
     if(KHM_FAILED(khc_read_int32(hc_v, L"WarnThreshold", &(tbl->threshold_warn))))\r
         khc_read_int32(hc_cw, L"WarnThreshold", &(tbl->threshold_warn));\r
-    if(KHM_FAILED(khc_read_int32(hc_v, L"CriticalThreshold", &(tbl->threshold_critical))))\r
-        khc_read_int32(hc_cw, L"CriticalThreshold", &(tbl->threshold_critical));\r
+    if(KHM_FAILED(khc_read_int32(hc_v, L"CriticalThreshold",\r
+                                 &(tbl->threshold_critical))))\r
+        khc_read_int32(hc_cw, L"CriticalThreshold",\r
+                       &(tbl->threshold_critical));\r
 \r
     /* and the font resources and stuff */\r
 \r
@@ -159,74 +390,74 @@ _skip_col:
 \r
     hdc = GetWindowDC(hwnd);\r
 \r
-    tbl->hf_header = CreateFont(\r
-        -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
-        0,0, /* escapement */\r
-        FW_THIN,\r
-        FALSE,\r
-        FALSE,\r
-        FALSE,\r
-        DEFAULT_CHARSET,\r
-        OUT_DEFAULT_PRECIS,\r
-        CLIP_DEFAULT_PRECIS,\r
-        DEFAULT_QUALITY,\r
-        FF_SWISS,\r
-        L"MS Shell Dlg");\r
+    tbl->hf_header =\r
+        CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
+                   0,0, /* escapement */\r
+                   FW_THIN,\r
+                   FALSE,\r
+                   FALSE,\r
+                   FALSE,\r
+                   DEFAULT_CHARSET,\r
+                   OUT_DEFAULT_PRECIS,\r
+                   CLIP_DEFAULT_PRECIS,\r
+                   DEFAULT_QUALITY,\r
+                   FF_SWISS,\r
+                   L"MS Shell Dlg");\r
 \r
     if(tbl->hf_header && tbl->hwnd_header)\r
         SendMessage(tbl->hwnd_header, WM_SETFONT, (WPARAM) tbl->hf_header, 0);\r
 \r
-    tbl->hf_bold_header = CreateFont(\r
-        -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
-        0,0, /* escapement */\r
-        FW_BOLD,\r
-        FALSE,\r
-        FALSE,\r
-        FALSE,\r
-        DEFAULT_CHARSET,\r
-        OUT_DEFAULT_PRECIS,\r
-        CLIP_DEFAULT_PRECIS,\r
-        DEFAULT_QUALITY,\r
-        FF_SWISS,\r
-        L"MS Shell Dlg");\r
-\r
-    tbl->hf_normal = CreateFont(\r
-        -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
-        0,0, /* escapement */\r
-        FW_THIN,\r
-        FALSE,\r
-        FALSE,\r
-        FALSE,\r
-        DEFAULT_CHARSET,\r
-        OUT_DEFAULT_PRECIS,\r
-        CLIP_DEFAULT_PRECIS,\r
-        DEFAULT_QUALITY,\r
-        FF_SWISS,\r
-        L"MS Shell Dlg");\r
-\r
-    tbl->hf_bold = CreateFont(\r
-        -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
-        0,0, /* escapement */\r
-        FW_BOLD,\r
-        FALSE,\r
-        FALSE,\r
-        FALSE,\r
-        DEFAULT_CHARSET,\r
-        OUT_DEFAULT_PRECIS,\r
-        CLIP_DEFAULT_PRECIS,\r
-        DEFAULT_QUALITY,\r
-        FF_SWISS,\r
-        L"MS Shell Dlg");\r
+    tbl->hf_bold_header =\r
+        CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
+                   0,0, /* escapement */\r
+                   FW_BOLD,\r
+                   FALSE,\r
+                   FALSE,\r
+                   FALSE,\r
+                   DEFAULT_CHARSET,\r
+                   OUT_DEFAULT_PRECIS,\r
+                   CLIP_DEFAULT_PRECIS,\r
+                   DEFAULT_QUALITY,\r
+                   FF_SWISS,\r
+                   L"MS Shell Dlg");\r
+\r
+    tbl->hf_normal =\r
+        CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
+                   0,0, /* escapement */\r
+                   FW_THIN,\r
+                   FALSE,\r
+                   FALSE,\r
+                   FALSE,\r
+                   DEFAULT_CHARSET,\r
+                   OUT_DEFAULT_PRECIS,\r
+                   CLIP_DEFAULT_PRECIS,\r
+                   DEFAULT_QUALITY,\r
+                   FF_SWISS,\r
+                   L"MS Shell Dlg");\r
+\r
+    tbl->hf_bold =\r
+        CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),0, /* width/height */\r
+                   0,0, /* escapement */\r
+                   FW_BOLD,\r
+                   FALSE,\r
+                   FALSE,\r
+                   FALSE,\r
+                   DEFAULT_CHARSET,\r
+                   OUT_DEFAULT_PRECIS,\r
+                   CLIP_DEFAULT_PRECIS,\r
+                   DEFAULT_QUALITY,\r
+                   FF_SWISS,\r
+                   L"MS Shell Dlg");\r
 \r
     ReleaseDC(hwnd, hdc);\r
 \r
-    khui_bitmap_from_hbmp(&(tbl->kbm_logo_shade),LoadImage(\r
-        khm_hInstance,\r
-        MAKEINTRESOURCE(IDB_LOGO_SHADE),\r
-        IMAGE_BITMAP,\r
-        0,\r
-        0,\r
-        LR_DEFAULTCOLOR));\r
+    khui_bitmap_from_hbmp(&(tbl->kbm_logo_shade),\r
+                          LoadImage(khm_hInstance,\r
+                                    MAKEINTRESOURCE(IDB_LOGO_SHADE),\r
+                                    IMAGE_BITMAP,\r
+                                    0,\r
+                                    0,\r
+                                    LR_DEFAULTCOLOR));\r
 \r
     tbl->hb_normal =        CreateSolidBrush(RGB(255,255,255));\r
     tbl->hb_grey =          CreateSolidBrush(RGB(240,240,240));\r
@@ -259,20 +490,25 @@ _skip_col:
         ADD_BITMAP(IDB_WDG_EXPAND);\r
         ADD_BITMAP(IDB_ID_SM);\r
         ADD_BITMAP(IDB_ID_DIS_SM);\r
+\r
         ADD_BITMAP(IDB_TK_NEW_SM);\r
         ADD_BITMAP(IDB_TK_REFRESH_SM);\r
         ADD_BITMAP(IDB_WDG_COLLAPSE_HI);\r
         ADD_BITMAP(IDB_WDG_EXPAND_HI);\r
+\r
         ADD_BITMAP(IDB_WDG_FLAG);\r
         ADD_BITMAP(IDB_WDG_CREDTYPE);\r
         ADD_BITMAP(IDB_FLAG_WARN);\r
         ADD_BITMAP(IDB_FLAG_EXPIRED);\r
+\r
         ADD_BITMAP(IDB_FLAG_CRITICAL);\r
         ADD_BITMAP(IDB_FLAG_RENEW);\r
         ADD_BITMAP(IDB_WDG_STUCK);\r
         ADD_BITMAP(IDB_WDG_STUCK_HI);\r
+\r
         ADD_BITMAP(IDB_WDG_STICK);\r
         ADD_BITMAP(IDB_WDG_STICK_HI);\r
+        ADD_BITMAP(IDB_TK_SM);\r
 \r
 #undef ADD_BITMAP\r
     }\r
@@ -288,12 +524,12 @@ _exit:
         khc_close_space(hc_cw);\r
     if(hc_vs)\r
         khc_close_space(hc_vs);\r
-    if(hc_v)\r
-        khc_close_space(hc_v);\r
     if(hc_cs)\r
         khc_close_space(hc_cs);\r
     if(clist)\r
         PFREE(clist);\r
+    /* we leave hc_v held, because tbl->csp_view is the same handle.\r
+       We keep that open until the view is unloaded. */\r
 }\r
 \r
 void \r
@@ -301,7 +537,7 @@ cw_update_creds(khui_credwnd_tbl * tbl)
 {\r
     kcdb_cred_comp_field * fields;\r
     kcdb_cred_comp_order comp_order;\r
-    khm_size i;\r
+    int i;\r
     khm_int32 n;\r
     khm_int32 delta;\r
     khm_handle hc;\r
@@ -330,8 +566,7 @@ cw_update_creds(khui_credwnd_tbl * tbl)
     for(i=0, n=0; i<tbl->n_cols; i++) {\r
         if((tbl->cols[i].flags & KHUI_CW_COL_SORT_INC) ||\r
            (tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC) ||\r
-           (tbl->cols[i].flags & KHUI_CW_COL_GROUP))\r
-        {\r
+           (tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {\r
             int si;\r
             /* we need to sort by this column */\r
             si = tbl->cols[i].sort_index;\r
@@ -356,8 +591,7 @@ cw_update_creds(khui_credwnd_tbl * tbl)
 \r
                Also, if we are sorting by credential type name, then\r
                we allow the primary credential type first before\r
-               others.\r
-            */\r
+               others. */\r
 \r
             if (fields[si].attrib == KCDB_ATTR_NAME ||\r
                 fields[si].attrib == KCDB_ATTR_TYPE_NAME)\r
@@ -384,8 +618,8 @@ cw_update_creds(khui_credwnd_tbl * tbl)
         khm_size s;\r
 \r
         kcdb_credset_get_size(tbl->credset, &s);\r
-        for(i=0;i<s;i++) {\r
-            if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset, \r
+        for(i=0;i< (int) s;i++) {\r
+            if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset,\r
                                                 (khm_int32) i, &hc)))\r
                 continue; /* lost a race */\r
             if(KHM_FAILED(kcdb_cred_get_attr(hc, khui_cw_flag_id, NULL, \r
@@ -413,6 +647,7 @@ cw_del_outline(khui_credwnd_outline *o) {
 \r
     if(o->header)\r
         PFREE(o->header);\r
+\r
     if ((o->flags & KHUI_CW_O_DATAALLOC) &&\r
         o->data)\r
         PFREE(o->data);\r
@@ -485,7 +720,7 @@ cw_timer_proc(HWND hwnd,
     khui_credwnd_tbl * tbl;\r
     khui_credwnd_row * r;\r
     khm_int32 nflags;\r
-    khm_size nr;\r
+    int nr;\r
     long ms;\r
     FILETIME ft;\r
     khm_size cbsize;\r
@@ -493,7 +728,7 @@ cw_timer_proc(HWND hwnd,
     tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);\r
     r = (khui_credwnd_row *) idEvent;\r
 \r
-    nr = r - tbl->rows;\r
+    nr = (int)(r - tbl->rows);\r
 \r
     if(nr < 0 || nr >= tbl->n_rows)\r
         return;\r
@@ -523,8 +758,9 @@ cw_timer_proc(HWND hwnd,
     }\r
 \r
     cbsize = sizeof(ft);\r
-    if(KHM_SUCCEEDED(kcdb_cred_get_attr((khm_handle) r->data, KCDB_ATTR_TIMELEFT, NULL, &ft, &cbsize)))\r
-    {\r
+    if(KHM_SUCCEEDED(kcdb_cred_get_attr((khm_handle) r->data,\r
+                                        KCDB_ATTR_TIMELEFT, NULL,\r
+                                        &ft, &cbsize))) {\r
         ms = FtIntervalMsToRepChange(&ft);\r
         if(ms > 0) {\r
             SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc);\r
@@ -545,7 +781,7 @@ cw_set_tbl_row_cred(khui_credwnd_tbl * tbl,
     if((int) tbl->n_total_rows <= row) {\r
         /* we need to resize the allocation */\r
         khui_credwnd_row * newrows;\r
-        khm_size newsize;\r
+        int newsize;\r
 \r
         newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);\r
         newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);\r
@@ -578,7 +814,7 @@ cw_set_tbl_row_header(khui_credwnd_tbl * tbl,
     if((int) tbl->n_total_rows <= row) {\r
         /* we need to resize the allocation */\r
         khui_credwnd_row * newrows;\r
-        khm_size newsize;\r
+        int newsize;\r
 \r
         newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT);\r
         newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize);\r
@@ -609,7 +845,7 @@ cw_update_outline(khui_credwnd_tbl * tbl)
     int i,j,n_rows;\r
     int level;\r
     int visible;\r
-    khm_size n_creds;\r
+    khm_size n_creds = 0;\r
     khm_handle prevcred = NULL;\r
     khm_handle thiscred = NULL;\r
     /* grouping[0..n_grouping-1] are the columns that we are going to\r
@@ -882,7 +1118,8 @@ cw_update_outline(khui_credwnd_tbl * tbl)
         \r
         /* we need to do this here too just in case we were already at\r
            the level we were supposed to be in */\r
-        visible = visible && (ol->flags & KHUI_CW_O_EXPAND);\r
+        if (ol)\r
+            visible = visible && (ol->flags & KHUI_CW_O_EXPAND);\r
 \r
         flags = cw_get_cred_exp_flags(tbl, thiscred);\r
         expstate |= flags;\r
@@ -1040,11 +1277,16 @@ cw_update_outline(khui_credwnd_tbl * tbl)
     tbl->flags |= KHUI_CW_TBL_ROW_DIRTY;\r
 \r
     tbl->flags &= ~KHUI_CW_TBL_COL_DIRTY;\r
+\r
+    if (tbl->cursor_row >= tbl->n_rows)\r
+        tbl->cursor_row = tbl->n_rows - 1;\r
+    if (tbl->cursor_row < 0)\r
+        tbl->cursor_row = 0;\r
 _exit:\r
     if(grouping)\r
         PFREE(grouping);\r
 \r
-    if (tbl->n_rows == 0)\r
+    if (n_creds == 0)\r
         khm_notify_icon_expstate(KHM_NOTIF_EMPTY);\r
     else if (expstate & CW_EXPSTATE_EXPIRED)\r
         khm_notify_icon_expstate(KHM_NOTIF_EXP);\r
@@ -1092,16 +1334,27 @@ cw_unload_view(khui_credwnd_tbl * tbl)
     }\r
 \r
     if(tbl->cols) {\r
-        khm_size i;\r
+        int i;\r
+\r
         for(i=0; i < tbl->n_cols; i++) {\r
             if(tbl->cols[i].title)\r
                 PFREE(tbl->cols[i].title);\r
             Header_DeleteItem(tbl->hwnd_header, 0);\r
+\r
+            if (tbl->cols[i].attr_id >= 0 &&\r
+                tbl->cols[i].attr_id <= KCDB_ATTR_MAX_ID &&\r
+                attr_to_action[tbl->cols[i].attr_id]) {\r
+\r
+                khui_check_action(attr_to_action[tbl->cols[i].attr_id], FALSE);\r
+\r
+            }\r
         }\r
         PFREE(tbl->cols);\r
         tbl->cols = NULL;\r
         tbl->n_cols = 0;\r
         tbl->n_total_cols = 0;\r
+\r
+        kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
     }\r
 \r
     if(tbl->rows) {\r
@@ -1112,6 +1365,11 @@ cw_unload_view(khui_credwnd_tbl * tbl)
     }\r
 \r
     khui_delete_bitmap(&tbl->kbm_logo_shade);\r
+\r
+    if (tbl->csp_view) {\r
+        khc_close_space(tbl->csp_view);\r
+        tbl->csp_view = NULL;\r
+    }\r
 }\r
 \r
 void \r
@@ -1208,7 +1466,7 @@ cw_update_extents(khui_credwnd_tbl * tbl,
 \r
         /* update the header control first */\r
 \r
-retry_update_scroll:\r
+    retry_update_scroll:\r
         GetClientRect(tbl->hwnd, &r);\r
 \r
         cl_w = r.right - r.left;\r
@@ -1302,19 +1560,19 @@ cw_erase_rect(HDC hdc,
     if(RectVisible(hdc, r_erase)) {\r
 \r
         switch(type) {\r
-            case CW_ER_BLANK:\r
-                hbr = tbl->hb_normal;\r
-                break;\r
+        case CW_ER_BLANK:\r
+            hbr = tbl->hb_normal;\r
+            break;\r
 \r
-            case CW_ER_GREY:\r
-                hbr = tbl->hb_grey;\r
-                break;\r
+        case CW_ER_GREY:\r
+            hbr = tbl->hb_grey;\r
+            break;\r
 \r
-            case CW_ER_SEL:\r
-                hbr = tbl->hb_sel;\r
-                break;\r
+        case CW_ER_SEL:\r
+            hbr = tbl->hb_sel;\r
+            break;\r
 \r
-            default:\r
+        default:\r
                 return;\r
         }\r
 \r
@@ -1510,57 +1768,308 @@ cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) {
 \r
     switch(ph->hdr.code) {\r
         /*TODO:Make it track smoother */\r
-        case HDN_BEGINTRACK:\r
-            {\r
-                if(tbl->cols[ph->iItem].flags & KHUI_CW_COL_FIXED_WIDTH)\r
-                    return TRUE;\r
+    case HDN_BEGINTRACK:\r
+        {\r
+            ZeroMemory(&hi, sizeof(hi));\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+\r
+            if(tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_WIDTH)\r
+                return TRUE;\r
+            else\r
+                return FALSE;\r
+        }\r
+\r
+    case HDN_TRACK:\r
+    case HDN_ENDTRACK:\r
+        {\r
+            int width;\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(ph->hdr.hwndFrom, ph->iItem, &hi);\r
+            Header_GetItemRect(ph->hdr.hwndFrom, ph->iItem, &r);\r
+            width = r.right - r.left;\r
+            if(width != tbl->cols[hi.iOrder].width) {\r
+                tbl->cols[hi.iOrder].width = width;\r
+                cw_update_extents(tbl, TRUE);\r
+                InvalidateRect(tbl->hwnd, NULL, FALSE);\r
+            }\r
+        }\r
+        break;\r
+\r
+    case HDN_BEGINDRAG:\r
+        {\r
+\r
+            ZeroMemory(&hi, sizeof(hi));\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+\r
+            if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_WIDTH) {\r
+                return TRUE;\r
+            } else {\r
+                return FALSE;\r
+            }\r
+        }\r
+        break;\r
+\r
+    case HDN_ENDDRAG:\r
+        {\r
+            int drag_start_index;\r
+            int drag_end_index;\r
+            int i;\r
+            khui_credwnd_col tcol;\r
+            int sort_index = 0;\r
+            khm_int32 old_flags;\r
+\r
+            if (ph->pitem == NULL)\r
+                return TRUE;\r
+\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+            drag_start_index = hi.iOrder;\r
+            drag_end_index = ph->pitem->iOrder;\r
+\r
+            /* the user dragged the column which was at drag_start_index\r
+               to drag_end_index. */\r
+\r
+            if (drag_end_index == drag_start_index)\r
+                return TRUE;\r
+\r
+            /* we don't allow dragging in to the "fixed" area. */\r
+            for (i=0; i < tbl->n_cols; i++) {\r
+                if (tbl->cols[i].attr_id >= 0)\r
+                    break;\r
+            }\r
+\r
+            if (drag_end_index <= i)\r
+                return TRUE;\r
\r
+            tcol = tbl->cols[drag_start_index];\r
+            if (drag_end_index < drag_start_index) {\r
+                MoveMemory(&tbl->cols[drag_end_index + 1],\r
+                           &tbl->cols[drag_end_index],\r
+                           sizeof(tbl->cols[0]) *\r
+                           (drag_start_index - drag_end_index));\r
+            } else {\r
+                MoveMemory(&tbl->cols[drag_start_index],\r
+                           &tbl->cols[drag_start_index + 1],\r
+                           sizeof(tbl->cols[0]) *\r
+                           (drag_end_index - drag_start_index));\r
+            }\r
+            tbl->cols[drag_end_index] = tcol;\r
+\r
+            old_flags = tbl->cols[drag_end_index].flags;\r
+\r
+            if (drag_end_index < tbl->n_cols - 1) {\r
+                khm_int32 tflags = tbl->cols[drag_end_index + 1].flags;\r
+\r
+                if (tflags & KHUI_CW_COL_GROUP) {\r
+                    tbl->cols[drag_end_index].flags |= KHUI_CW_COL_GROUP;\r
+                }\r
+\r
+                if ((tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) &&\r
+                    !(old_flags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))\r
+                    tbl->cols[drag_end_index].flags |= KHUI_CW_COL_SORT_INC;\r
+            }\r
+\r
+            if (drag_end_index > 0) {\r
+                khm_int32 tflags = tbl->cols[drag_end_index - 1].flags;\r
+\r
+                if (!(tflags & KHUI_CW_COL_GROUP))\r
+                    tbl->cols[drag_end_index].flags &= ~KHUI_CW_COL_GROUP;\r
+\r
+                if (!(tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)))\r
+                    tbl->cols[drag_end_index].flags &=\r
+                        ~(KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);\r
+            }\r
+\r
+            if (old_flags != tbl->cols[drag_end_index].flags) {\r
+                cw_hditem_from_tbl_col(&tbl->cols[drag_end_index], &hi);\r
+                hi.mask = HDI_FORMAT;\r
+                Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+            }\r
+\r
+            if ((old_flags ^ tbl->cols[drag_end_index].flags) &\r
+                KHUI_CW_COL_GROUP)\r
+                tbl->flags |= KHUI_CW_TBL_COL_DIRTY;\r
+\r
+            for (i=0; i < tbl->n_cols; i++) {\r
+                if (tbl->cols[i].attr_id < 0)\r
+                    continue;\r
+\r
+                if (tbl->cols[i].flags &\r
+                    (KHUI_CW_COL_GROUP |\r
+                     KHUI_CW_COL_SORT_INC |\r
+                     KHUI_CW_COL_SORT_DEC))\r
+                    tbl->cols[i].sort_index = sort_index++;\r
                 else\r
-                    return FALSE;\r
+                    break;\r
             }\r
 \r
-        case HDN_TRACK:\r
-        case HDN_ENDTRACK:\r
-            {\r
-                int width;\r
-                hi.mask = HDI_ORDER;\r
-                Header_GetItem(ph->hdr.hwndFrom, ph->iItem, &hi);\r
-                Header_GetItemRect(ph->hdr.hwndFrom, ph->iItem, &r);\r
-                width = r.right - r.left;\r
-                if(width != tbl->cols[hi.iOrder].width) {\r
-                    tbl->cols[hi.iOrder].width = width;\r
-                    cw_update_extents(tbl, TRUE);\r
-                    InvalidateRect(tbl->hwnd, NULL, FALSE);\r
+            tbl->flags |= KHUI_CW_TBL_CUSTVIEW;\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, FALSE);\r
+\r
+            return FALSE;\r
+        }\r
+        break;\r
+\r
+    case HDN_ITEMCLICK:\r
+        {\r
+            int idx;\r
+            int hidx;\r
+\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+            idx = hi.iOrder;\r
+\r
+            if (idx == 0 || idx >= tbl->n_cols)\r
+                return FALSE;\r
+\r
+            if (tbl->cols[idx].flags &\r
+                (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) {\r
+\r
+                tbl->cols[idx].flags ^=\r
+                    (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC);\r
+\r
+                cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);\r
+                hi.mask = HDI_FORMAT;\r
+                Header_SetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+\r
+            } else {\r
+                int i;\r
+                int sort_idx = 0;\r
+\r
+                for (i=0; i <= idx; i++) {\r
+                    if (tbl->cols[i].attr_id < 0)\r
+                        continue;\r
+\r
+                    if (!(tbl->flags &\r
+                          (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) {\r
+                        tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;\r
+\r
+                        cw_hditem_from_tbl_col(&tbl->cols[i], &hi);\r
+                        hi.mask = HDI_FORMAT;\r
+                        hidx = Header_OrderToIndex(tbl->hwnd_header, i);\r
+                        Header_SetItem(tbl->hwnd_header, hidx, &hi);\r
+                    }\r
+\r
+                    tbl->cols[i].sort_index = sort_idx++;\r
                 }\r
             }\r
-            break;\r
 \r
-        case NM_CUSTOMDRAW:\r
-            {\r
-                LPNMCUSTOMDRAW cd;\r
-                int idx;\r
-\r
-                cd = (LPNMCUSTOMDRAW) ph;\r
-                switch(cd->dwDrawStage)\r
-                {\r
-                case CDDS_PREPAINT:\r
-                    return CDRF_NOTIFYITEMDRAW;\r
-\r
-                case CDDS_ITEMPREPAINT:\r
-                    return CDRF_NOTIFYPOSTPAINT;\r
-\r
-                case CDDS_ITEMPOSTPAINT:\r
-                    if(cd->lItemlParam == CW_CA_FLAGS)\r
-                        idx = IDB_WDG_FLAG;\r
-                    else if(cd->lItemlParam == CW_CA_TYPEICON)\r
-                        idx = IDB_WDG_CREDTYPE;\r
-                    else\r
-                        idx = -1;\r
+            tbl->flags |= KHUI_CW_TBL_CUSTVIEW;\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, FALSE);\r
+\r
+        }\r
+        break;\r
+\r
+    case HDN_ITEMDBLCLICK:\r
+        {\r
+            int idx;\r
+            int hidx;\r
 \r
-                    khui_ilist_draw_id(tbl->ilist, idx, cd->hdc, cd->rc.left, cd->rc.top, 0);\r
-                    return 0;\r
+            hi.mask = HDI_ORDER;\r
+            Header_GetItem(tbl->hwnd_header, ph->iItem, &hi);\r
+            idx = hi.iOrder;\r
+\r
+            if (idx == 0 || idx >= tbl->n_cols)\r
+                return FALSE;\r
+\r
+            if (tbl->cols[idx].flags & KHUI_CW_COL_GROUP) {\r
+                /* we are removing grouping from this level */\r
+\r
+                int i;\r
+\r
+                for (i=idx; i < tbl->n_cols; i++) {\r
+                    if (!(tbl->cols[i].flags &\r
+                          (KHUI_CW_COL_GROUP |\r
+                           KHUI_CW_COL_SORT_INC |\r
+                           KHUI_CW_COL_SORT_DEC)))\r
+                        break;\r
+\r
+                    tbl->cols[i].flags &=\r
+                        ~(KHUI_CW_COL_GROUP |\r
+                          KHUI_CW_COL_SORT_DEC |\r
+                          KHUI_CW_COL_SORT_INC);\r
+\r
+                    cw_hditem_from_tbl_col(&tbl->cols[idx], &hi);\r
+                    hi.mask = HDI_FORMAT;\r
+                    hidx = Header_OrderToIndex(tbl->hwnd_header, i);\r
+                    Header_SetItem(tbl->hwnd_header, hidx, &hi);\r
+                }\r
+\r
+            } else {\r
+                int i;\r
+                int sort_index = 0;\r
+\r
+                for (i=0; i <= idx; i++) {\r
+                    if (tbl->cols[i].attr_id < 0)\r
+                        continue;\r
+\r
+                    if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP)) {\r
+                        tbl->cols[i].flags |= KHUI_CW_COL_GROUP;\r
+\r
+                        if (!(tbl->cols[i].flags &\r
+                              (KHUI_CW_COL_SORT_INC |\r
+                               KHUI_CW_COL_SORT_DEC)))\r
+                            tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC;\r
+\r
+                        cw_hditem_from_tbl_col(&tbl->cols[i], &hi);\r
+                        hi.mask = HDI_FORMAT;\r
+                        hidx = Header_OrderToIndex(tbl->hwnd_header, i);\r
+                        Header_SetItem(tbl->hwnd_header, hidx, &hi);\r
+                    }\r
+\r
+                    tbl->cols[i].sort_index = sort_index++;\r
                 }\r
             }\r
-            break;\r
+\r
+            tbl->flags |= KHUI_CW_TBL_COL_DIRTY;\r
+            tbl->flags |= KHUI_CW_TBL_CUSTVIEW;\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, FALSE);\r
+        }\r
+        break;\r
+\r
+    case NM_CUSTOMDRAW:\r
+        {\r
+            LPNMCUSTOMDRAW cd;\r
+            int idx;\r
+\r
+            cd = (LPNMCUSTOMDRAW) ph;\r
+            switch(cd->dwDrawStage) {\r
+            case CDDS_PREPAINT:\r
+                return CDRF_NOTIFYITEMDRAW;\r
+\r
+            case CDDS_ITEMPREPAINT:\r
+                return CDRF_NOTIFYPOSTPAINT;\r
+\r
+            case CDDS_ITEMPOSTPAINT:\r
+                if(cd->lItemlParam == CW_CA_FLAGS)\r
+                    idx = IDB_WDG_FLAG;\r
+                else if(cd->lItemlParam == CW_CA_TYPEICON)\r
+                    idx = IDB_WDG_CREDTYPE;\r
+                else\r
+                    idx = -1;\r
+\r
+                khui_ilist_draw_id(tbl->ilist, idx, cd->hdc, cd->rc.left, cd->rc.top, 0);\r
+                return 0;\r
+            }\r
+        }\r
+        break;\r
     }\r
     return 0;\r
 }\r
@@ -1572,6 +2081,7 @@ cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 \r
     kmq_subscribe_hwnd(KMSG_CRED, hwnd);\r
     kmq_subscribe_hwnd(KMSG_KCDB, hwnd);\r
+    kmq_subscribe_hwnd(KMSG_KMM, hwnd);\r
 \r
     /* freed in cw_wm_destroy  */\r
     tbl = PMALLOC(sizeof(*tbl));\r
@@ -1584,12 +2094,15 @@ cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     SetWindowLongPtr(hwnd, 0, (LONG_PTR) tbl);\r
 #pragma warning(pop)\r
 \r
+    cw_refresh_attribs(hwnd);\r
+\r
     tbl->hwnd_header = CreateWindowEx(\r
         0,\r
         WC_HEADER,\r
         (LPWSTR) NULL,\r
         WS_CHILD | HDS_BUTTONS |\r
-        HDS_FULLDRAG | HDS_HORZ | HDS_HOTTRACK\r
+        HDS_FULLDRAG | HDS_HORZ | HDS_HOTTRACK |\r
+        HDS_DRAGDROP\r
 #if (_WIN32_WINNT >= 0x501)\r
         | ((IS_COMMCTL6())?HDS_FLAT:0)\r
 #endif\r
@@ -1627,16 +2140,19 @@ cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
 }\r
 \r
-LRESULT \r
+LRESULT\r
 cw_wm_destroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
 {\r
     khui_credwnd_tbl * tbl;\r
 \r
     kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);\r
     kmq_unsubscribe_hwnd(KMSG_KCDB, hwnd);\r
+    kmq_unsubscribe_hwnd(KMSG_KMM, hwnd);\r
 \r
     tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0);\r
 \r
+    cw_save_view(tbl, NULL);\r
+\r
     cw_unload_view(tbl);\r
 \r
     PFREE(tbl);\r
@@ -1814,7 +2330,7 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                             khui_ilist_draw_id(tbl->ilist, IDB_FLAG_CRITICAL, hdc, x, y, 0);\r
                         } else if(flag == CW_EXPSTATE_EXPIRED) {\r
                             khui_ilist_draw_id(tbl->ilist, IDB_FLAG_EXPIRED, hdc, x, y, 0);\r
-                        } else {\r
+                        } else if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) {\r
                             khm_int32 flags;\r
 \r
                             if (KHM_SUCCEEDED(kcdb_cred_get_flags((khm_handle) tbl->rows[i].data, &flags)) &&\r
@@ -1823,6 +2339,11 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                                                    IDB_FLAG_RENEW,\r
                                                    hdc,\r
                                                    x, y, 0);\r
+                            } else {\r
+                                khui_ilist_draw_id(tbl->ilist,\r
+                                                   IDB_TK_SM,\r
+                                                   hdc,\r
+                                                   x, y, 0);\r
                             }\r
                         }\r
                     }\r
@@ -1944,6 +2465,7 @@ cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); \r
 \r
     kmq_wm_begin(lParam, &m);\r
+\r
     if(m->type == KMSG_CRED) {\r
         switch (m->subtype) {\r
         case KMSG_CRED_ROOTDELTA:\r
@@ -1982,7 +2504,173 @@ cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 \r
             InvalidateRect(hwnd, NULL, FALSE);\r
         }\r
+        else if (m->subtype == KMSG_KCDB_ATTRIB &&\r
+                 (m->uparam == KCDB_OP_INSERT ||\r
+                  m->uparam == KCDB_OP_DELETE)) {\r
+            cw_refresh_attribs(hwnd);\r
+        }\r
+    } else if (m->type == KMSG_KMM &&\r
+               m->subtype == KMSG_KMM_I_DONE) {\r
+\r
+        if (tbl->flags & KHUI_CW_TBL_COLSKIP) {\r
+            wchar_t cname[KCONF_MAXCCH_NAME];\r
+            khm_size cb;\r
+\r
+            cname[0] = L'\0';\r
+\r
+            if (tbl->csp_view) {\r
+                cb = sizeof(cname);\r
+                khc_get_config_space_name(tbl->csp_view,\r
+                                          cname,\r
+                                          &cb);\r
+            }\r
+\r
+            cw_unload_view(tbl);\r
+\r
+            cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd);\r
+            cw_insert_header_cols(tbl);\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, TRUE);\r
+        }\r
+\r
+    } else if (m->type == KMSG_ACT &&\r
+               m->subtype == KMSG_ACT_ACTIVATE) {\r
+        /* a column selector menu item was activated */\r
+\r
+        khm_int32 attr_id;\r
+        khm_int32 action;\r
+        khui_action * paction;\r
+        int i;\r
+        int first_non_fixed = -1;\r
+\r
+        action = m->uparam;\r
+        paction = khui_find_action(action);\r
+\r
+        if (paction == NULL)\r
+            goto _skip_action;\r
+\r
+        attr_id = (khm_int32)(INT_PTR) paction->data;\r
+\r
+        if (attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID)\r
+            goto _skip_action;\r
+\r
+        for (i=0; i < tbl->n_cols; i++) {\r
+            if (tbl->cols[i].attr_id >= 0 &&\r
+                first_non_fixed == -1)\r
+                first_non_fixed = i;\r
+\r
+            if (tbl->cols[i].attr_id == attr_id)\r
+                break;\r
+        }\r
+\r
+        if (first_non_fixed == i &&\r
+            i == tbl->n_cols - 1) {\r
+            /* this is the only non-fixed column.  We don't allow\r
+               deleting it, althoguh there's nothing wrong with doing\r
+               so other than not being very useful. */\r
+            goto _skip_action;\r
+        }\r
+\r
+        if (i < tbl->n_cols) {\r
+            khm_int32 sort_index;\r
+\r
+            /* we need to remove a column */\r
+\r
+            Header_DeleteItem(tbl->hwnd_header, i);\r
+            sort_index = tbl->cols[i].sort_index;\r
+\r
+            if (tbl->cols[i].title)\r
+                PFREE(tbl->cols[i].title);\r
+            tbl->cols[i].title = NULL;\r
+\r
+            if (i < tbl->n_cols - 1) {\r
+                MoveMemory(&tbl->cols[i], &tbl->cols[i+1],\r
+                           sizeof(tbl->cols[0]) * (tbl->n_cols - (i + 1)));\r
+            }\r
+            tbl->n_cols--;\r
+\r
+            /* fix the sort index */\r
+            if (sort_index >= 0) {\r
+                for (i=0; i < tbl->n_cols; i++) {\r
+                    if (tbl->cols[i].sort_index > sort_index)\r
+                        tbl->cols[i].sort_index--;\r
+                }\r
+            }\r
+\r
+            tbl->flags |= KHUI_CW_TBL_COL_DIRTY;\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, TRUE);\r
+\r
+            khui_check_action(attr_to_action[attr_id], FALSE);\r
+\r
+            tbl->flags |= KHUI_CW_TBL_CUSTVIEW;\r
+\r
+        } else {\r
+            /* we need to add a column */\r
+            wchar_t buf[KCDB_MAXCCH_SHORT_DESC];\r
+            khm_size cb;\r
+            khm_int32 idx = tbl->n_cols;\r
+            HDITEM hi;\r
+\r
+            /* for now, we only allow KHUI_CW_COL_INITIAL columns */\r
+            if (tbl->n_rows == tbl->n_total_rows)\r
+                goto _skip_action;\r
+\r
+            cb = sizeof(buf);\r
+            if (KHM_FAILED(kcdb_attrib_describe(attr_id,\r
+                                                buf,\r
+                                                &cb,\r
+                                                KCDB_TS_SHORT)))\r
+                goto _skip_action;\r
+\r
+            tbl->cols[idx].attr_id = attr_id;\r
+            tbl->cols[idx].width = 100;\r
+            tbl->cols[idx].x = -1;\r
+            tbl->cols[idx].flags = 0;\r
+            tbl->cols[idx].sort_index = -1;\r
+            tbl->cols[idx].title = PMALLOC(cb);\r
+#ifdef DEBUG\r
+            assert(tbl->cols[idx].title);\r
+#endif\r
+            if (!tbl->cols[idx].title)\r
+                goto _skip_action;\r
+\r
+            StringCbCopy(tbl->cols[idx].title,\r
+                         cb,\r
+                         buf);\r
+\r
+            tbl->n_cols++;\r
+\r
+            cw_hditem_from_tbl_col(&(tbl->cols[idx]), &hi);\r
+            Header_InsertItem(tbl->hwnd_header, 512, &hi);\r
+\r
+            tbl->flags |= KHUI_CW_TBL_COL_DIRTY;\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, TRUE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, TRUE);\r
+\r
+            khui_check_action(attr_to_action[attr_id], TRUE);\r
+\r
+            tbl->flags |= KHUI_CW_TBL_CUSTVIEW;\r
+        }\r
+\r
+        kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
+\r
+    _skip_action:\r
+        ;\r
     }\r
+\r
     return kmq_wm_end(m, rv);\r
 }\r
 \r
@@ -2013,7 +2701,7 @@ cw_select_outline(khui_credwnd_outline * o,
 static void \r
 cw_unselect_all(khui_credwnd_tbl * tbl)\r
 {\r
-    khm_size i;\r
+    int i;\r
 \r
     for(i=0; i<tbl->n_rows; i++) {\r
         tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED;\r
@@ -2069,7 +2757,7 @@ cw_update_outline_selection_state(khui_credwnd_tbl * tbl,
 static void \r
 cw_update_selection_state(khui_credwnd_tbl * tbl)\r
 {\r
-    khm_size i;\r
+    int i;\r
 \r
     cw_select_outline_level(tbl->outline, FALSE);\r
 \r
@@ -2219,7 +2907,7 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
 static void\r
 cw_select_all(khui_credwnd_tbl * tbl)\r
 {\r
-    khm_size i;\r
+    int i;\r
 \r
     for(i=0; i<tbl->n_rows; i++) {\r
         tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED;\r
@@ -2307,7 +2995,6 @@ cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam)
                                     (select)?KCDB_CRED_FLAG_SELECTED:0,\r
                                     KCDB_CRED_FLAG_SELECTED);\r
             }\r
-\r
         }\r
     } else if (extend) {\r
         int range_begin;\r
@@ -2349,7 +3036,7 @@ cw_toggle_outline_state(khui_credwnd_tbl * tbl,
 \r
     old_range_begin = o->start;\r
     old_range_end = o->start + o->length - 1;\r
-    \r
+\r
     o->flags ^= KHUI_CW_O_EXPAND;\r
 \r
     cw_update_outline(tbl);\r
@@ -2448,7 +3135,7 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        (nm_row != tbl->mouse_row)) {\r
         nm_state &= ~CW_MOUSE_WMASK;\r
     }\r
-    \r
+\r
     if(!(nm_state & CW_MOUSE_LDOWN) && \r
        (tbl->mouse_state & CW_MOUSE_LDOWN) &&\r
        tbl->mouse_row == nm_row) {\r
@@ -2490,6 +3177,15 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         } else {\r
             /* click on a row */\r
             cw_select_row(tbl, nm_row, wParam);\r
+\r
+            if (tbl->mouse_col == nm_col &&\r
+                nm_col >= 0 &&\r
+                tbl->cols[nm_col].attr_id == CW_CA_FLAGS &&\r
+                !(tbl->rows[nm_row].flags & KHUI_CW_ROW_HEADER)) {\r
+                /* clicked on a cred icon */\r
+\r
+                cw_properties(hwnd);\r
+            }\r
         }\r
     }\r
 \r
@@ -3270,6 +3966,7 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 \r
     case KHUI_ACTION_LAYOUT_ID:\r
         {\r
+            cw_save_view(tbl, NULL);\r
             cw_unload_view(tbl);\r
 \r
             cw_load_view(tbl, L"ByIdentity", hwnd);\r
@@ -3288,6 +3985,7 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 \r
     case KHUI_ACTION_LAYOUT_LOC:\r
         {\r
+            cw_save_view(tbl, NULL);\r
             cw_unload_view(tbl);\r
 \r
             cw_load_view(tbl, L"ByLocation", hwnd);\r
@@ -3300,7 +3998,47 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             InvalidateRect(tbl->hwnd, NULL, TRUE);\r
 \r
             khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), \r
-                              KHUI_ACTION_LAYOUT_LOC);\r
+                                    KHUI_ACTION_LAYOUT_LOC);\r
+            kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
+        }\r
+        break;\r
+\r
+    case KHUI_ACTION_LAYOUT_TYPE:\r
+        {\r
+            cw_save_view(tbl, NULL);\r
+            cw_unload_view(tbl);\r
+\r
+            cw_load_view(tbl, L"ByType", hwnd);\r
+            cw_insert_header_cols(tbl);\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, FALSE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, TRUE);\r
+\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), \r
+                                    KHUI_ACTION_LAYOUT_TYPE);\r
+            kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
+        }\r
+        break;\r
+\r
+    case KHUI_ACTION_LAYOUT_CUST:\r
+        {\r
+            cw_save_view(tbl, NULL);\r
+            cw_unload_view(tbl);\r
+\r
+            cw_load_view(tbl, L"Custom_0", hwnd);\r
+            cw_insert_header_cols(tbl);\r
+\r
+            cw_update_creds(tbl);\r
+            cw_update_outline(tbl);\r
+            cw_update_extents(tbl, FALSE);\r
+\r
+            InvalidateRect(tbl->hwnd, NULL, TRUE);\r
+\r
+            khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT),\r
+                                    KHUI_ACTION_LAYOUT_CUST);\r
             kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0);\r
         }\r
         break;\r
@@ -3337,6 +4075,33 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         }\r
         break;\r
 \r
+    case KHUI_PACTION_PGUP_EXTEND:\r
+    case KHUI_PACTION_PGUP:\r
+        {\r
+            khm_int32 new_row;\r
+            WPARAM wp;\r
+            RECT r;\r
+\r
+            if (LOWORD(wParam) == KHUI_PACTION_PGUP_EXTEND)\r
+                wp = MK_SHIFT;\r
+            else\r
+                wp = 0;\r
+\r
+            GetClientRect(hwnd, &r);\r
+\r
+            new_row = tbl->cursor_row -\r
+                ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;\r
+\r
+            if (new_row < 0)\r
+                new_row = 0;\r
+            if (new_row >= (int) tbl->n_rows)\r
+                new_row = (int) tbl->n_rows - 1;\r
+\r
+            cw_select_row(tbl, new_row, wp);\r
+            cw_ensure_row_visible(hwnd, tbl, new_row);\r
+        }\r
+        break;\r
+\r
     case KHUI_PACTION_DOWN:\r
     case KHUI_PACTION_DOWN_EXTEND:\r
     case KHUI_PACTION_DOWN_TOGGLE:\r
@@ -3368,6 +4133,33 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         }\r
         break;\r
 \r
+    case KHUI_PACTION_PGDN_EXTEND:\r
+    case KHUI_PACTION_PGDN:\r
+        {\r
+            khm_int32 new_row;\r
+            RECT r;\r
+            WPARAM wp;\r
+\r
+            if (LOWORD(wParam) == KHUI_PACTION_PGDN_EXTEND)\r
+                wp = MK_SHIFT;\r
+            else\r
+                wp = 0;\r
+\r
+            GetClientRect(hwnd, &r);\r
+\r
+            new_row = tbl->cursor_row +\r
+                ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height;\r
+\r
+            if (new_row < 0)\r
+                new_row = 0;\r
+            if (new_row >= (int) tbl->n_rows)\r
+                new_row = (int) tbl->n_rows - 1;\r
+\r
+            cw_select_row(tbl, new_row, wp);\r
+            cw_ensure_row_visible(hwnd, tbl, new_row);\r
+        }\r
+        break;\r
+\r
     case KHUI_PACTION_SELALL:\r
         {\r
             cw_select_all(tbl);\r
@@ -3439,6 +4231,8 @@ cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             }\r
 \r
             r++;\r
+            if (r >= (int) tbl->n_rows)\r
+                r = (int)tbl->n_rows - 1;\r
 \r
             cw_select_row(tbl, r, 0);\r
         }\r
@@ -3465,6 +4259,15 @@ cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     x += tbl->scr_left - r.left;\r
     y += tbl->scr_top - tbl->header_height - r.top;\r
 \r
+    if (y < 0) {\r
+        /* context menu for header control */\r
+        khm_menu_show_panel(KHUI_MENU_CWHEADER_CTX,\r
+                            GET_X_LPARAM(lParam),\r
+                            GET_Y_LPARAM(lParam));\r
+\r
+        return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
+    }\r
+\r
     row = y / tbl->cell_height;\r
 \r
     if(row < 0 || row >= (int) tbl->n_rows)\r
@@ -3591,18 +4394,25 @@ khm_unregister_credwnd_class(void) {
 HWND \r
 khm_create_credwnd(HWND parent) {\r
     RECT r;\r
+    HWND hwnd;\r
+\r
+    ZeroMemory(attr_to_action, sizeof(attr_to_action));\r
+\r
     GetClientRect(parent, &r);\r
-    return CreateWindowEx(\r
-        0,\r
-        MAKEINTATOM(khui_credwnd_cls),\r
-        L"",\r
-        WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,\r
-        r.left,\r
-        r.top,\r
-        r.right - r.left,\r
-        r.bottom - r.top,\r
-        parent,\r
-        NULL,\r
-        khm_hInstance,\r
-        NULL);\r
+\r
+    hwnd = CreateWindowEx\r
+        (0,\r
+         MAKEINTATOM(khui_credwnd_cls),\r
+         L"",\r
+         WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,\r
+         r.left,\r
+         r.top,\r
+         r.right - r.left,\r
+         r.bottom - r.top,\r
+         parent,\r
+         NULL,\r
+         khm_hInstance,\r
+         NULL);\r
+\r
+    return hwnd;\r
 }\r
index 33e00bacb057fe8810e37a3f66312577fbe913d8..0c1e766b52f8d747e2a473c6559b79c26708ec7d 100644 (file)
 extern khm_int32 khui_cw_flag_id;\r
 \r
 /* The expiration states */\r
-#define CW_EXPSTATE_NONE        0\r
-#define CW_EXPSTATE_WARN        1024\r
-#define CW_EXPSTATE_CRITICAL    2048\r
-#define CW_EXPSTATE_EXPIRED     3072\r
+#define CW_EXPSTATE_NONE        0x00000000\r
+#define CW_EXPSTATE_WARN        0x00000400\r
+#define CW_EXPSTATE_CRITICAL    0x00000800\r
+#define CW_EXPSTATE_EXPIRED     0x00000c00\r
 \r
-#define CW_EXPSTATE_MASK        3072\r
+#define CW_EXPSTATE_MASK        0x00000c00\r
 \r
 typedef struct khui_credwnd_outline_t {\r
     khm_int32   flags;      /* combination of KHUI_CW_O_* */\r
@@ -61,12 +61,12 @@ typedef struct khui_credwnd_outline_t {
     TDCL(struct khui_credwnd_outline_t);\r
 } khui_credwnd_outline;\r
 \r
-#define KHUI_CW_O_EXPAND     0x00000001\r
-#define KHUI_CW_O_STICKY     0x00000002\r
-#define KHUI_CW_O_VISIBLE    0x00000004\r
-#define KHUI_CW_O_SHOWFLAG   0x00000008\r
-#define KHUI_CW_O_SELECTED   0x00000010\r
-#define KHUI_CW_O_DATAALLOC  0x00000020\r
+#define KHUI_CW_O_EXPAND        0x00000001\r
+#define KHUI_CW_O_STICKY        0x00000002\r
+#define KHUI_CW_O_VISIBLE       0x00000004\r
+#define KHUI_CW_O_SHOWFLAG      0x00000008\r
+#define KHUI_CW_O_SELECTED      0x00000010\r
+#define KHUI_CW_O_DATAALLOC     0x00000020\r
 \r
 typedef struct khui_credwnd_row_t {\r
     khm_int32   flags;\r
@@ -76,10 +76,10 @@ typedef struct khui_credwnd_row_t {
     khm_size idx_end;\r
 } khui_credwnd_row;\r
 \r
-#define KHUI_CW_ROW_CRED        2\r
-#define KHUI_CW_ROW_HEADER      4\r
-#define KHUI_CW_ROW_TIMERSET    8\r
-#define KHUI_CW_ROW_SELECTED    16\r
+#define KHUI_CW_ROW_CRED        0x00000002\r
+#define KHUI_CW_ROW_HEADER      0x00000004\r
+#define KHUI_CW_ROW_TIMERSET    0x00000008\r
+#define KHUI_CW_ROW_SELECTED    0x00000010\r
 \r
 /* row allocation */\r
 /* initial number of rows to be allocated */\r
@@ -102,13 +102,13 @@ typedef struct khui_credwnd_col_t {
 /* allocation increment, if we run out of space */\r
 #define KHUI_CW_COL_INCREMENT   16\r
 \r
-#define KHUI_CW_COL_AUTOSIZE    1\r
-#define KHUI_CW_COL_SORT_INC    2\r
-#define KHUI_CW_COL_SORT_DEC    4\r
-#define KHUI_CW_COL_GROUP       8\r
-#define KHUI_CW_COL_FIXED_WIDTH 16\r
-#define KHUI_CW_COL_FIXED_POS   32\r
-#define KHUI_CW_COL_META        64\r
+#define KHUI_CW_COL_AUTOSIZE    0x00000001\r
+#define KHUI_CW_COL_SORT_INC    0x00000002\r
+#define KHUI_CW_COL_SORT_DEC    0x00000004\r
+#define KHUI_CW_COL_GROUP       0x00000008\r
+#define KHUI_CW_COL_FIXED_WIDTH 0x00000010\r
+#define KHUI_CW_COL_FIXED_POS   0x00000020\r
+#define KHUI_CW_COL_META        0x00000040\r
 \r
 /* Custom column attributes (are not kcdb attributes) */\r
 #define CW_CA_FLAGS -1\r
@@ -122,6 +122,9 @@ typedef struct khui_credwnd_col_t {
 typedef struct khui_credwnd_tbl_t {\r
     HWND hwnd;                  /* the window that this table belongs to */\r
 \r
+    khm_handle csp_view;        /* handle to the configuration space\r
+                                   that defined the view */\r
+\r
     khm_int32 scr_top;          /* screen units */\r
     khm_int32 scr_left;         /* screen units */\r
     khm_int32 ext_width;        /* screen units */\r
@@ -134,19 +137,19 @@ typedef struct khui_credwnd_tbl_t {
 \r
     khui_credwnd_col * cols;    /* n_cols elements */\r
     khui_credwnd_row * rows;    /* n_rows elements */\r
-    khm_size  n_cols;\r
-    khm_size  n_total_cols;     /* number of columns actually\r
+    int       n_cols;\r
+    int       n_total_cols;     /* number of columns actually\r
                                    allocated in cols */\r
-    khm_size  n_rows;\r
-    khm_size  n_total_rows;     /* number of rows actually allocated\r
+    int       n_rows;\r
+    int       n_total_rows;     /* number of rows actually allocated\r
                                    in rows */\r
 \r
     khui_credwnd_outline * outline;\r
 \r
     khm_int32 flags;            /* combo of KHUI_CW_TBL_* */\r
 \r
-    khm_int32 cursor_row;       /* cursor and selection */\r
-    khm_int32 anchor_row;       /* anchor, for range selections */\r
+    int       cursor_row;       /* cursor and selection */\r
+    int       anchor_row;       /* anchor, for range selections */\r
 \r
     /* view parameters */\r
     khm_int32 hpad;\r
@@ -204,6 +207,8 @@ typedef struct khui_credwnd_tbl_t {
 #define KHUI_CW_TBL_COL_DIRTY   0x00000002\r
 #define KHUI_CW_TBL_ROW_DIRTY   0x00000004\r
 #define KHUI_CW_TBL_ACTIVE      0x00000100\r
+#define KHUI_CW_TBL_CUSTVIEW    0x00000200\r
+#define KHUI_CW_TBL_COLSKIP     0x00000400\r
 \r
 /* mouse_state constants */\r
 #define CW_MOUSE_NONE       0x00000000 /* nothing interesting */\r
diff --git a/src/windows/identity/ui/debugfuncs.c b/src/windows/identity/ui/debugfuncs.c
new file mode 100644 (file)
index 0000000..b18ef42
--- /dev/null
@@ -0,0 +1,252 @@
+/*\r
+ * Copyright (c) 2005 Massachusetts Institute of Technology\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person\r
+ * obtaining a copy of this software and associated documentation\r
+ * files (the "Software"), to deal in the Software without\r
+ * restriction, including without limitation the rights to use, copy,\r
+ * modify, merge, publish, distribute, sublicense, and/or sell copies\r
+ * of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be\r
+ * included in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+#include<tchar.h>\r
+\r
+#include<shlwapi.h>\r
+#include<khmapp.h>\r
+\r
+#include<stdio.h>\r
+\r
+#if DEBUG\r
+#include<assert.h>\r
+#endif\r
+\r
+#define LOGFILENAME "nidmdbg.log"\r
+\r
+CRITICAL_SECTION cs_log;\r
+FILE * logfile = NULL;\r
+BOOL log_started = FALSE;\r
+\r
+wchar_t *\r
+severity_string(kherr_severity severity) {\r
+    switch(severity) {\r
+    case KHERR_FATAL:\r
+       return L"FATAL";\r
+\r
+    case KHERR_ERROR:\r
+       return L"ERROR";\r
+\r
+    case KHERR_WARNING:\r
+       return L"Warning";\r
+\r
+    case KHERR_INFO:\r
+       return L"Info";\r
+\r
+    case KHERR_DEBUG_3:\r
+       return L"Debug(3)";\r
+\r
+    case KHERR_DEBUG_2:\r
+       return L"Debug(2)";\r
+\r
+    case KHERR_DEBUG_1:\r
+       return L"Debug(1)";\r
+\r
+    case KHERR_NONE:\r
+       return L"(None)";\r
+\r
+    default:\r
+       return L"(Unknown severity)";\r
+    }\r
+}\r
+\r
+void\r
+fprint_systime(FILE * f, SYSTEMTIME *psystime) {\r
+    fprintf(logfile,\r
+            "%d-%d-%d %02d:%02d:%02d.%03d",\r
+\r
+            (int) psystime->wYear,\r
+            (int) psystime->wMonth,\r
+            (int) psystime->wDay,\r
+\r
+            (int) psystime->wHour,\r
+            (int) psystime->wMinute,\r
+            (int) psystime->wSecond,\r
+            (int) psystime->wMilliseconds);\r
+}\r
+\r
+void KHMAPI\r
+debug_event_handler(enum kherr_ctx_event e,\r
+                   kherr_context * c) {\r
+    kherr_event * evt;\r
+\r
+    EnterCriticalSection(&cs_log);\r
+\r
+    if (!logfile)\r
+       goto _done;\r
+\r
+    if (e == KHERR_CTX_BEGIN) {\r
+        SYSTEMTIME systime;\r
+\r
+        GetSystemTime(&systime);\r
+       fprintf(logfile,\r
+               "%d\t",\r
+               c->serial);\r
+\r
+        fprint_systime(logfile, &systime);\r
+\r
+        fprintf(logfile,\r
+                "\t<< Context begin --\n");\r
+\r
+    } else if (e == KHERR_CTX_DESCRIBE) {\r
+       evt = kherr_get_desc_event(c);\r
+       if (evt) {\r
+           kherr_evaluate_event(evt);\r
+           fprintf(logfile,\r
+                   "%d\t  Description: %S\n",\r
+                   c->serial,\r
+                   (evt->long_desc)? evt->long_desc: evt->short_desc);\r
+       }\r
+    } else if (e == KHERR_CTX_END) {\r
+        SYSTEMTIME systime;\r
+\r
+       fprintf(logfile,\r
+               "%d\t",\r
+               c->serial);\r
+\r
+        GetSystemTime(&systime);\r
+        fprint_systime(logfile, &systime);\r
+\r
+        fprintf(logfile,\r
+                "\t>> Context end --\n");\r
+\r
+    } else if (e == KHERR_CTX_EVTCOMMIT) {\r
+       evt = kherr_get_last_event(c);\r
+       if (evt && (evt->short_desc || evt->long_desc)) {\r
+           SYSTEMTIME systime;\r
+\r
+           kherr_evaluate_event(evt);\r
+           FileTimeToSystemTime(&evt->time_ft, &systime);\r
+           \r
+           fprintf(logfile,\r
+                   "%d[%d](%S)\t",\r
+                   c->serial,\r
+                   evt->thread_id,\r
+                   (evt->facility ? evt->facility: L""));\r
+\r
+            fprint_systime(logfile, &systime);\r
+\r
+            fprintf(logfile,\r
+                    "\t%S: %S %S%S%S %S%S%S\n",\r
+\r
+                   severity_string(evt->severity),\r
+\r
+                   (evt->short_desc ? evt->short_desc: L""),\r
+\r
+                   (evt->short_desc ? L"(":L""),\r
+                   (evt->long_desc ? evt->long_desc: L""),\r
+                   (evt->short_desc ? L")":L""),\r
+\r
+                   (evt->suggestion ? L"[":L""),\r
+                   (evt->suggestion ? evt->suggestion: L""),\r
+                   (evt->suggestion ? L"]":L"")\r
+                   );\r
+       }\r
+    }\r
+\r
+ _done:\r
+\r
+    LeaveCriticalSection(&cs_log);\r
+}\r
+\r
+void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf) {\r
+#ifdef DEBUG\r
+    assert(cb_buf > sizeof(wchar_t));\r
+#endif\r
+    *buf = L'\0';\r
+\r
+    GetTempPath((DWORD) cb_buf / sizeof(wchar_t), buf);\r
+\r
+    StringCbCat(buf, cb_buf, _T(LOGFILENAME));\r
+}\r
+\r
+void khm_start_file_log(void) {\r
+    wchar_t temppath[MAX_PATH];\r
+    khm_handle cs_cw = NULL;\r
+    khm_int32 t = 0;\r
+\r
+    EnterCriticalSection(&cs_log);\r
+\r
+    if (log_started)\r
+       goto _done;\r
+\r
+    if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &cs_cw)))\r
+       goto _done;\r
+\r
+    if (KHM_FAILED(khc_read_int32(cs_cw, L"LogToFile", &t)) ||\r
+       !t)\r
+       goto _done;\r
+\r
+    khm_get_file_log_path(sizeof(temppath), temppath);\r
+\r
+    logfile = _wfopen(temppath, L"w");\r
+\r
+    kherr_add_ctx_handler(debug_event_handler,\r
+                         KHERR_CTX_BEGIN |\r
+                         KHERR_CTX_END |\r
+                         KHERR_CTX_DESCRIBE |\r
+                         KHERR_CTX_EVTCOMMIT,\r
+                         0);\r
+\r
+    log_started = TRUE;\r
+\r
+ _done:\r
+    if (cs_cw)\r
+       khc_close_space(cs_cw);\r
+\r
+    LeaveCriticalSection(&cs_log);\r
+}\r
+\r
+void khm_stop_file_log(void) {\r
+\r
+    EnterCriticalSection(&cs_log);\r
+\r
+    if (!log_started)\r
+       goto _done;\r
+\r
+    kherr_remove_ctx_handler(debug_event_handler, 0);\r
+\r
+    if (logfile)\r
+       fclose (logfile);\r
+    logfile = NULL;\r
+\r
+    log_started = FALSE;\r
+\r
+ _done:\r
+    LeaveCriticalSection(&cs_log);\r
+}\r
+\r
+void khm_init_debug(void) {\r
+    InitializeCriticalSection(&cs_log);\r
+\r
+    khm_start_file_log();\r
+}\r
+\r
+void khm_exit_debug(void) {\r
+    khm_stop_file_log();\r
+\r
+    DeleteCriticalSection(&cs_log);\r
+}\r
diff --git a/src/windows/identity/ui/debugfuncs.h b/src/windows/identity/ui/debugfuncs.h
new file mode 100644 (file)
index 0000000..4c378a3
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+ * Copyright (c) 2005 Massachusetts Institute of Technology\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person\r
+ * obtaining a copy of this software and associated documentation\r
+ * files (the "Software"), to deal in the Software without\r
+ * restriction, including without limitation the rights to use, copy,\r
+ * modify, merge, publish, distribute, sublicense, and/or sell copies\r
+ * of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be\r
+ * included in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+#ifndef __NETIDMGR_DEBUGFUNCS_H\r
+#define __NETIDMGR_DEBUGFUNCS_H\r
+\r
+void khm_init_debug(void);\r
+void khm_exit_debug(void);\r
+\r
+void khm_start_file_log(void);\r
+void khm_stop_file_log(void);\r
+void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf);\r
+\r
+#endif\r
index 8dcb29e7a66f097ad2f67b181bb352fb2421d3d9..cf60a3e6a38b22c96abf1af201a0452e212eeb26 100644 (file)
Binary files a/src/windows/identity/ui/images/app_notify_none.ico and b/src/windows/identity/ui/images/app_notify_none.ico differ
index 710a962980673bb3ee124dfabc06edf4958888c0..99ffbc411b5f9cf6244bd011297fdb6194a5478b 100644 (file)
Binary files a/src/windows/identity/ui/images/cfg_plugin.ico and b/src/windows/identity/ui/images/cfg_plugin.ico differ
diff --git a/src/windows/identity/ui/images/cfg_plugin_dis.ico b/src/windows/identity/ui/images/cfg_plugin_dis.ico
new file mode 100644 (file)
index 0000000..853ad40
Binary files /dev/null and b/src/windows/identity/ui/images/cfg_plugin_dis.ico differ
diff --git a/src/windows/identity/ui/images/cfg_plugin_err.ico b/src/windows/identity/ui/images/cfg_plugin_err.ico
new file mode 100644 (file)
index 0000000..1b1b4ee
Binary files /dev/null and b/src/windows/identity/ui/images/cfg_plugin_err.ico differ
index 98da87d5501fdce8ca5d2120f2e3460c7a2d5d90..01515992940e7b993d0ac3899e93d7075482f8ca 100644 (file)
Binary files a/src/windows/identity/ui/images/tk-delete.bmp and b/src/windows/identity/ui/images/tk-delete.bmp differ
index c89285c610020899f23ec1e486f0a6b7ea1370fc..1e099e6f18ef3890f084838575e4a71cbce42b21 100644 (file)
Binary files a/src/windows/identity/ui/images/tk-sm.bmp and b/src/windows/identity/ui/images/tk-sm.bmp differ
index 7f12c7ffaf2803dacc43e1fb73e4983893bbba6a..203f5b02b0cdb02dcc1288661e4876815bce4ccb 100644 (file)
@@ -36,6 +36,7 @@
 #define KHERR_HMODULE khm_hInstance\r
 #define KHERR_FACILITY khm_facility\r
 #define KHERR_FACILITY_ID 3\r
+#define NOEXPORT\r
 \r
 #include<khdefs.h>\r
 #include<khlist.h>\r
@@ -63,6 +64,7 @@
 #include<propertywnd.h>\r
 #include<configwnd.h>\r
 #include<aboutwnd.h>\r
+#include<debugfuncs.h>\r
 \r
 #include<reqdaemon.h>\r
 #include<notifier.h>\r
index b139effdb400449375ef036346eae5859d706e89..0a746199be522a06cabac0925879019d1b47a9bd 100644 (file)
@@ -68,6 +68,9 @@ IDI_ID                  ICON                    "..\\..\\images\\id.ico"
 IDI_APPICON_WARN        ICON                    "..\\..\\images\\app_state_warn.ico"\r
 IDI_APPICON_EXP         ICON                    "..\\..\\images\\app_state_exp.ico"\r
 IDI_APPICON_OK          ICON                    "..\\..\\images\\app_state_ok.ico"\r
+IDI_CFG_PLUGIN          ICON                    "..\\..\\images\\cfg_plugin.ico"\r
+IDI_CFG_PLUGIN_ERR      ICON                    "..\\..\\images\\cfg_plugin_err.ico"\r
+IDI_CFG_PLUGIN_DIS      ICON                    "..\\..\\images\\cfg_plugin_dis.ico"\r
 \r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
@@ -245,14 +248,13 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN\r
     LTEXT           "Title",IDC_CFG_TITLE,0,0,357,20,SS_CENTERIMAGE\r
     CONTROL         "",IDC_CFG_NODELIST,"SysTreeView32",TVS_HASBUTTONS | \r
-                    TVS_HASLINES | TVS_LINESATROOT | WS_TABSTOP,0,20,100,182\r
+                    TVS_HASLINES | TVS_LINESATROOT | TVS_TRACKSELECT | \r
+                    WS_TABSTOP | 0x800,0,20,100,182\r
     LTEXT           "Static",IDC_CFG_PANE,102,20,255,182,NOT WS_VISIBLE | \r
                     WS_BORDER\r
     PUSHBUTTON      "&Ok",IDOK,162,205,78,16\r
     PUSHBUTTON      "&Cancel",IDCANCEL,246,205,51,16\r
     PUSHBUTTON      "&Apply",IDAPPLY,303,205,51,16,WS_DISABLED\r
-    PUSHBUTTON      "C&hange Summary ...",IDC_CFG_SUMMARY,3,205,76,16,\r
-                    WS_DISABLED\r
 END\r
 \r
 IDD_CFG_GENERIC DIALOGEX 0, 0, 255, 182\r
@@ -267,22 +269,29 @@ IDD_CFG_GENERAL DIALOGEX 0, 0, 255, 182
 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU\r
 FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
 BEGIN\r
-    GROUPBOX        "Startup",IDC_CFG_STARTUP_GROUP,7,7,241,50\r
+    GROUPBOX        "Startup / Shutdown",IDC_CFG_STARTUP_GROUP,7,7,241,50\r
     CONTROL         "&Obtain new credentials at startup (if none are present)",\r
                     IDC_CFG_AUTOINIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,\r
                     16,22,196,10\r
+    CONTROL         "&Destroy all credentials on exit",IDC_CFG_DESTROYALL,\r
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,39,111,10\r
     CONTROL         "&Start NetIDMgr during Windows logon",IDC_CFG_AUTOSTART,\r
-                    "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,16,\r
-                    38,135,10\r
-    GROUPBOX        "Other",IDC_CFG_OTHER,7,63,241,54\r
+                    "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | \r
+                    WS_TABSTOP,16,48,135,10\r
+    GROUPBOX        "Other",IDC_CFG_OTHER,7,63,241,85\r
     CONTROL         "&Run NetIDMgr in system tray after window close",\r
                     IDC_CFG_KEEPRUNNING,"Button",BS_AUTOCHECKBOX | \r
                     WS_TABSTOP,16,78,170,10\r
     CONTROL         "Monitor network connectivity",IDC_CFG_NETDETECT,"Button",\r
                     BS_AUTOCHECKBOX | WS_TABSTOP,16,96,106,10\r
+    CONTROL         "Log trace events to trace log at the following location:",\r
+                    IDC_CFG_LOGTOFILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,\r
+                    16,113,225,10\r
+    EDITTEXT        IDC_CFG_LOGPATH,16,127,225,14,ES_AUTOHSCROLL | \r
+                    ES_READONLY\r
     CONTROL         "A&utomatically import Windows logon identity",\r
                     IDC_CFG_AUTOIMPORT,"Button",BS_AUTOCHECKBOX | NOT \r
-                    WS_VISIBLE | WS_TABSTOP,16,147,165,10\r
+                    WS_VISIBLE | WS_TABSTOP,16,158,165,10\r
 END\r
 \r
 IDD_CFG_IDENTITIES DIALOGEX 0, 0, 255, 182\r
@@ -300,45 +309,55 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
 EXSTYLE WS_EX_CONTROLPARENT\r
 FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
 BEGIN\r
-    CONTROL         "&Monitor credential expiration",IDC_NOTIF_MONITOR,\r
-                    "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,7,\r
-                    111,139,10\r
     CONTROL         "&Renew automatically at",IDC_NOTIF_RENEW,"Button",\r
                     BS_AUTOCHECKBOX | WS_TABSTOP,7,9,100,10\r
     EDITTEXT        IDC_NOTIF_RENEW_THR,122,7,126,14,ES_AUTOHSCROLL\r
+    CONTROL         "Renew at &half life intervals when possible",\r
+                    IDC_NOTIF_HALFLIFE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,\r
+                    48,27,148,10\r
     CONTROL         "Initial warning at",IDC_NOTIF_WARN1,"Button",\r
-                    BS_AUTOCHECKBOX | WS_TABSTOP,7,31,100,10\r
-    EDITTEXT        IDC_NOTIF_WARN1_THR,122,29,126,14,ES_AUTOHSCROLL\r
+                    BS_AUTOCHECKBOX | WS_TABSTOP,7,46,100,10\r
+    EDITTEXT        IDC_NOTIF_WARN1_THR,122,44,126,14,ES_AUTOHSCROLL\r
     CONTROL         "Final warning at",IDC_NOTIF_WARN2,"Button",\r
-                    BS_AUTOCHECKBOX | WS_TABSTOP,7,53,100,10\r
-    EDITTEXT        IDC_NOTIF_WARN2_THR,122,51,126,14,ES_AUTOHSCROLL\r
+                    BS_AUTOCHECKBOX | WS_TABSTOP,7,68,100,10\r
+    EDITTEXT        IDC_NOTIF_WARN2_THR,122,66,126,14,ES_AUTOHSCROLL\r
+    CONTROL         "&Monitor credential expiration",IDC_NOTIF_MONITOR,\r
+                    "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,7,\r
+                    103,139,10\r
 END\r
 \r
 IDD_CFG_PLUGINS DIALOGEX 0, 0, 255, 182\r
 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU\r
+EXSTYLE WS_EX_CONTROLPARENT\r
 FONT 8, "MS Shell Dlg", 400, 0, 0x1\r
 BEGIN\r
     CONTROL         "",IDC_CFG_PLUGINS,"SysListView32",LVS_REPORT | \r
-                    LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,75,168\r
-    GROUPBOX        "Plugin",IDC_CFG_PLUGINGRP,86,7,162,103\r
-    LTEXT           "Description",IDC_CFG_LBL_DESC,90,20,36,8\r
-    EDITTEXT        IDC_CFG_DESC,134,17,109,14,ES_AUTOHSCROLL | ES_READONLY\r
-    LTEXT           "Status",IDC_CFG_LBL_STATE,90,38,22,8\r
-    EDITTEXT        IDC_CFG_STATE,134,35,109,14,ES_AUTOHSCROLL | ES_READONLY\r
-    LTEXT           "Depends on",IDC_CFG_LBL_DEPS,90,52,39,8\r
-    LISTBOX         IDC_CFG_DEPS,134,52,109,34,LBS_SORT | \r
-                    LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP\r
-    PUSHBUTTON      "Enable",IDC_CFG_ENABLE,134,90,50,14\r
-    PUSHBUTTON      "Disable",IDC_CFG_DISABLE,193,90,50,14\r
-    GROUPBOX        "Provided by",IDC_CFG_PROVGRP,86,111,162,47\r
-    LTEXT           "Module",IDC_CFG_LBL_MOD,90,124,24,8\r
-    EDITTEXT        IDC_CFG_MODULE,134,121,109,14,ES_AUTOHSCROLL | \r
+                    LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | \r
+                    WS_TABSTOP,7,7,75,168\r
+    ICON            IDI_CFG_PLUGIN,IDC_CFG_ICON,87,11,20,20\r
+    EDITTEXT        IDC_CFG_DESC,128,7,120,30,ES_MULTILINE | ES_AUTOVSCROLL | \r
                     ES_READONLY\r
-    LTEXT           "Vendor",IDC_CFG_LBL_VEN,90,142,24,8\r
-    EDITTEXT        IDC_CFG_VENDOR,133,139,110,14,ES_AUTOHSCROLL | \r
+    LTEXT           "&Module",IDC_CFG_LBL_MOD,87,43,24,8\r
+    EDITTEXT        IDC_CFG_MODULE,128,43,120,12,ES_AUTOHSCROLL | \r
                     ES_READONLY\r
-    PUSHBUTTON      "Register new plugin ...",IDC_CFG_REGISTER,163,161,85,14,\r
+    LTEXT           "&Version",IDC_STATIC,87,59,24,8\r
+    EDITTEXT        IDC_CFG_VERSION,128,59,120,12,ES_AUTOHSCROLL | \r
+                    ES_READONLY\r
+    LTEXT           "Ve&ndor",IDC_CFG_LBL_VEN,87,75,24,8\r
+    EDITTEXT        IDC_CFG_VENDOR,128,75,120,12,ES_AUTOHSCROLL | \r
+                    ES_READONLY\r
+    LTEXT           "De&pends on",IDC_CFG_LBL_DEPS,87,93,39,8\r
+    LISTBOX         IDC_CFG_DEPS,128,93,120,34,LBS_SORT | \r
+                    LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP\r
+    LTEXT           "&Status",IDC_CFG_LBL_STATE,87,129,22,8\r
+    EDITTEXT        IDC_CFG_STATE,128,129,120,12,ES_AUTOHSCROLL | \r
+                    ES_READONLY\r
+    PUSHBUTTON      "&Enable ...",IDC_CFG_ENABLE,128,144,50,14,WS_DISABLED\r
+    PUSHBUTTON      "&Disable ...",IDC_CFG_DISABLE,198,144,50,14,WS_DISABLED\r
+    PUSHBUTTON      "&Unregister plugin ...",IDC_CFG_UNREGISTER,87,161,72,14,\r
                     WS_DISABLED\r
+    PUSHBUTTON      "&Register new plugin ...",IDC_CFG_REGISTER,169,161,79,\r
+                    14,NOT WS_VISIBLE | WS_DISABLED\r
 END\r
 \r
 IDD_CFG_IDENTITY DIALOGEX 0, 0, 255, 182\r
@@ -483,10 +502,8 @@ BEGIN
     BEGIN\r
         LEFTMARGIN, 7\r
         RIGHTMARGIN, 248\r
-        VERTGUIDE, 86\r
-        VERTGUIDE, 90\r
-        VERTGUIDE, 134\r
-        VERTGUIDE, 243\r
+        VERTGUIDE, 87\r
+        VERTGUIDE, 128\r
         TOPMARGIN, 7\r
         BOTTOMMARGIN, 175\r
     END\r
@@ -554,7 +571,7 @@ BEGIN
     IDS_CFG_GENERAL_SHORT   "General"\r
     IDS_ACTION_NEW_CRED     "&New credentials ..."\r
     IDS_ACTION_PASSWD_ID    "Change &password ..."\r
-    IDS_ACTION_CHOOSE_COLS  "Choose columns ..."\r
+    IDS_ACTION_CHOOSE_COLS  "View columns"\r
     IDS_ACTION_DEBUG_WINDOW "Debug window ..."\r
     IDS_ACTION_VIEW_REFRESH "Refresh"\r
     IDS_MENU_LAYOUT         "Layout"\r
@@ -693,6 +710,32 @@ BEGIN
     IDS_NC_ID_DEF           "<p>This identity is the default</p>"\r
     IDS_NC_ID_WDEF          "<p>Will be the default. (<a id=""NotDef"">Don't make default</a>)</p>"\r
     IDS_NC_ID_NDEF          "<p>Not default identity.  (<a id=""MakeDef"">make default</a>)</p>"\r
+    IDS_PACTION_YES         "&Yes"\r
+    IDS_PACTION_NO          "&No"\r
+    IDS_PACTION_YESALL      "Y&es to all"\r
+    IDS_PACTION_NOALL       "N&o to all"\r
+    IDS_PACTION_KEEP        "&Keep"\r
+    IDS_PACTION_REMOVE      "&Remove"\r
+    IDS_PACTION_DISCARD     "&Discard"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_CFG_IT_MOD          "Changes need to be applied"\r
+    IDS_CFG_IT_APP          "Changes have been applied"\r
+    IDS_CFG_IT_NONE         "No changes"\r
+    IDS_CFG_NODESC          "(Description for plugin %s is not available)"\r
+    IDS_CFG_P_DELCNFT       "About to disable plugin %s"\r
+    IDS_CFG_P_DELCNFM       "Are you sure you want to disable plugin %s ?\n\nOnce disabled, the services provided by the plugin will no longer be available. In addition, any other plugins that depend on this plugin will also become non functional.\n\nNetIDMgr will need to be restarted for the plugin to be deactivated."\r
+    IDS_CFG_P_DELCNFS       "The following plugins depend on this plugin : %s"\r
+    IDS_CFG_P_DELNDEP       "No other plugins depend on this plugin."\r
+    IDS_CFG_P_ENBCNFT       "About to enable plugin %s"\r
+    IDS_CFG_P_ENBCNFM       "The plugin %s will be marked as enabled.  The plugin will be come active the next time NetIDMgr is started."\r
+    IDS_PISTATE_FAILINIT    "Failed to initialize"\r
+    IDS_CFG_P_UNRCNFT       "Unregistering plugin %s"\r
+    IDS_CFG_P_UNRCNFM       "Are you sure you want to unregister plugin %s? In addition to this plugin, any other plugins that are provided by the same module will also be unregistered.\n\nThe plugin will no longer be loaded for subsequent sessions of NetIDMgr."\r
+    IDS_CFG_P_UNRCNFS       "Note that if the plugin was registered by a seprate installer, it should be unregistered by the same installer and not through NetIDMgr.\n\nThe following plugins will be unregistered: %s"\r
+    IDS_ACTION_LAYOUT_CUST  "Custom"\r
 END\r
 \r
 #endif    // English (U.S.) resources\r
index 6f7f9bd47cb5bd38c695d42d92f91637530686a5..6987db3ef4a750d2494dd4b270508fe22acf85d9 100644 (file)
@@ -26,6 +26,7 @@
 \r
 #include<shlwapi.h>\r
 #include<khmapp.h>\r
+#include<netidmgr_intver.h>\r
 \r
 #if DEBUG\r
 #include<assert.h>\r
@@ -38,6 +39,8 @@ khm_ui_4 khm_commctl_version = 0;
 \r
 khm_startup_options khm_startup;\r
 \r
+khm_version app_version = {KH_VERSION_LIST};\r
+\r
 void khm_init_gui(void) {\r
     khui_init_actions();\r
     khui_init_rescache();\r
@@ -45,9 +48,11 @@ void khm_init_gui(void) {
     khui_init_toolbar();\r
     khm_init_notifier();\r
     khm_init_config();\r
+    khm_init_debug();\r
 }\r
 \r
 void khm_exit_gui(void) {\r
+    khm_exit_debug();\r
     khm_exit_config();\r
     khm_exit_notifier();\r
     khui_exit_toolbar();\r
@@ -127,6 +132,7 @@ void khm_register_window_classes(void) {
         ICC_HOTKEY_CLASS |\r
         ICC_LISTVIEW_CLASSES |\r
         ICC_TAB_CLASSES |\r
+        ICC_INTERNET_CLASSES |\r
 #if (_WIN32_WINNT >= 0x501)\r
         ((IS_COMMCTL6())?\r
          ICC_LINK_CLASS |\r
@@ -319,42 +325,61 @@ BOOL khm_check_ps_message(LPMSG pmsg) {
     return FALSE;\r
 }\r
 \r
-WPARAM khm_message_loop(void) {\r
+static HACCEL ha_menu;\r
+\r
+WPARAM khm_message_loop_int(khm_boolean * p_exit) {\r
     int r;\r
     MSG msg;\r
-    HACCEL ha_menu;\r
 \r
-    ha_menu = khui_create_global_accel_table();\r
-    while(r = GetMessage(&msg, NULL, 0,0)) {\r
+    while((r = GetMessage(&msg, NULL, 0,0)) &&\r
+          (p_exit == NULL || *p_exit)) {\r
         if(r == -1)\r
             break;\r
         if(!khm_check_dlg_message(&msg) &&\r
-            !khm_check_ps_message(&msg) &&\r
-            !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {\r
+           !khm_check_ps_message(&msg) &&\r
+           !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {\r
             TranslateMessage(&msg);\r
             DispatchMessage(&msg);\r
         }\r
     }\r
-    DestroyAcceleratorTable(ha_menu);\r
+\r
     return msg.wParam;\r
 }\r
 \r
+WPARAM khm_message_loop(void) {\r
+    WPARAM w;\r
+    ha_menu = khui_create_global_accel_table();\r
+    w = khm_message_loop_int(NULL);\r
+    DestroyAcceleratorTable(ha_menu);\r
+    return w;\r
+}\r
+\r
+/* Handles all context closures which have a signalled error state.\r
+   If the context is a top level context, then the errors are\r
+   displayed. */\r
 void KHMAPI\r
-khm_module_load_ctx_handler(enum kherr_ctx_event evt,\r
-                            kherr_context * c) {\r
+khm_err_ctx_completion_handler(enum kherr_ctx_event evt,\r
+                               kherr_context * c) {\r
     kherr_event * e;\r
     khui_alert * a;\r
 \r
+    /* we only handle top level contexts here.  For others, we allow\r
+       the child contexts to fold upward silently. */\r
+    if (c->parent || !kherr_is_error_i(c))\r
+        return;\r
+\r
     for(e = kherr_get_first_event(c);\r
         e;\r
         e = kherr_get_next_event(e)) {\r
 \r
+        if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING)\r
+            continue;\r
+\r
         kherr_evaluate_event(e);\r
 \r
-        if ((e->severity == KHERR_ERROR ||\r
-             e->severity == KHERR_WARNING) &&\r
-            e->short_desc &&\r
-            e->long_desc) {\r
+        /* we only report errors if there is enough information to\r
+           present a message. */\r
+        if (e->short_desc && e->long_desc) {\r
 \r
             khui_alert_create_empty(&a);\r
 \r
@@ -369,9 +394,6 @@ khm_module_load_ctx_handler(enum kherr_ctx_event evt,
             khui_alert_release(a);\r
         }\r
     }\r
-\r
-    kherr_remove_ctx_handler(khm_module_load_ctx_handler,\r
-                             c->serial);\r
 }\r
 \r
 static wchar_t helpfile[MAX_PATH] = L"";\r
@@ -405,19 +427,7 @@ HWND khm_html_help(HWND hwnd, wchar_t * suffix,
 }\r
 \r
 void khm_load_default_modules(void) {\r
-    kherr_context * c;\r
-\r
-    _begin_task(KHERR_CF_TRANSITIVE);\r
-\r
     kmm_load_default_modules();\r
-\r
-    c = kherr_peek_context();\r
-    kherr_add_ctx_handler(khm_module_load_ctx_handler,\r
-                          KHERR_CTX_END,\r
-                          c->serial);\r
-    kherr_release_context(c);\r
-\r
-    _end_task();\r
 }\r
 \r
 int WINAPI WinMain(HINSTANCE hInstance,\r
@@ -445,6 +455,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
 \r
     khc_load_schema(NULL, schema_uiconfig);\r
 \r
+ _start_app:\r
+\r
     if(!slave) {\r
 \r
         /* set this so that we don't accidently invoke an API that\r
@@ -466,6 +478,10 @@ int WINAPI WinMain(HINSTANCE hInstance,
 \r
         kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);\r
 \r
+        kherr_add_ctx_handler(khm_err_ctx_completion_handler,\r
+                              KHERR_CTX_END,\r
+                              0);\r
+\r
         /* load the standard plugins */\r
         khm_load_default_modules();\r
 \r
@@ -478,6 +494,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
         if (!khm_startup.no_main_window)\r
             khm_show_main_window();\r
 \r
+        khm_refresh_config();\r
+\r
         rv = (int) khm_message_loop();\r
 \r
         kmq_set_completion_handler(KMSG_CRED, NULL);\r
@@ -497,6 +515,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
         wchar_t mapname[256];\r
         DWORD tid;\r
         void * xfer;\r
+        khm_query_app_version query_app_version;\r
 \r
         CloseHandle(h_appmutex);\r
 \r
@@ -513,6 +532,58 @@ int WINAPI WinMain(HINSTANCE hInstance,
         if (!hwnd)\r
             return 2;\r
 \r
+        /* first check if the remote instance supports a version\r
+           query */\r
+\r
+        StringCbPrintf(mapname, sizeof(mapname),\r
+                       QUERY_APP_VER_MAP_FMT,\r
+                       (tid = GetCurrentThreadId()));\r
+\r
+        hmap = CreateFileMapping(INVALID_HANDLE_VALUE,\r
+                                 NULL,\r
+                                 PAGE_READWRITE,\r
+                                 0,\r
+                                 4096,\r
+                                 mapname);\r
+\r
+        if (hmap == NULL)\r
+            return 3;\r
+\r
+        xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,\r
+                             sizeof(query_app_version));\r
+\r
+        if (xfer) {\r
+            ZeroMemory(&query_app_version, sizeof(query_app_version));\r
+\r
+            query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;\r
+            query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;\r
+            query_app_version.ver_caller = app_version;\r
+\r
+            query_app_version.request_swap = TRUE;\r
+\r
+            memcpy(xfer, &query_app_version, sizeof(query_app_version));\r
+\r
+            SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION,\r
+                        0, (LPARAM) tid);\r
+\r
+            memcpy(&query_app_version, xfer, sizeof(query_app_version));\r
+\r
+            UnmapViewOfFile(xfer);\r
+            xfer = NULL;\r
+        }\r
+\r
+        CloseHandle(hmap);\r
+        hmap = NULL;\r
+\r
+        if (query_app_version.code == KHM_ERROR_SUCCESS &&\r
+            query_app_version.request_swap) {\r
+            /* the request for swap was granted.  We can now\r
+               initialize our instance as the master instance. */\r
+\r
+            slave = FALSE;\r
+            goto _start_app;\r
+        }\r
+\r
         StringCbPrintf(mapname, sizeof(mapname),\r
                        COMMANDLINE_MAP_FMT,\r
                        (tid = GetCurrentThreadId()));\r
@@ -546,7 +617,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
             CloseHandle(hmap);\r
     }\r
 \r
-#if 0\r
+#if defined(DEBUG) && ( defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))\r
     /* writes a report of memory leaks to the specified file.  Should\r
        only be enabled on development versions. */\r
     PDUMP("memleak.txt");\r
index 10270f2a09f1e15b0918c7785740e8082d6558f6..fc3a64b0c97cbda9644d729e16f79b02e8d0a715 100644 (file)
@@ -81,6 +81,8 @@ void add_action_to_menu(HMENU hm, khui_action * act,
     wchar_t buf[MAX_RES_STRING] = L"";\r
     wchar_t accel[MAX_RES_STRING] = L"";\r
 \r
+    assert(!act || act->cmd);\r
+\r
     mii.cbSize = sizeof(mii);\r
     mii.fMask = 0;\r
 \r
@@ -90,9 +92,13 @@ void add_action_to_menu(HMENU hm, khui_action * act,
     } else {\r
         khui_menu_def * def;\r
 \r
-        LoadString(khm_hInstance, \r
-                   act->is_caption, \r
-                   buf, ARRAYLENGTH(buf));\r
+        if (act->caption) {\r
+            StringCbCopy(buf, sizeof(buf), act->caption);\r
+        } else {\r
+            LoadString(khm_hInstance, \r
+                       act->is_caption, \r
+                       buf, ARRAYLENGTH(buf));\r
+        }\r
 \r
         if(khui_get_cmd_accel_string(act->cmd, accel, \r
                                      ARRAYLENGTH(accel))) {\r
@@ -126,10 +132,12 @@ void add_action_to_menu(HMENU hm, khui_action * act,
             mii.hbmpItem = HBMMENU_CALLBACK;\r
         }\r
 \r
-        def = khui_find_menu(act->cmd);\r
-        if(def) {\r
-            mii.fMask |= MIIM_SUBMENU;\r
-            mii.hSubMenu = mm_create_menu_from_def(def, FALSE);\r
+        if (flags & KHUI_ACTIONREF_SUBMENU) {\r
+            def = khui_find_menu(act->cmd);\r
+            if(def) {\r
+                mii.fMask |= MIIM_SUBMENU;\r
+                mii.hSubMenu = mm_create_menu_from_def(def, FALSE);\r
+            }\r
         }\r
 \r
         if(flags & KHUI_ACTIONREF_DEFAULT)\r
@@ -153,6 +161,21 @@ static void refresh_menu_item(HMENU hm, khui_action * act,
     else {\r
         khui_menu_def * def;\r
 \r
+        /* first check if the menu item is there.  Otherwise we need\r
+           to add it. */\r
+        mii.fMask = MIIM_STATE;\r
+        if (!GetMenuItemInfo(hm, act->cmd, FALSE, &mii)) {\r
+            /* the 1000 is fairly arbitrary, but there should be much\r
+               less menu items on a menu anyway.  If there are that\r
+               many items, the system would be unusable to the extent\r
+               that the order of the items would be the least of our\r
+               worries. */\r
+            add_action_to_menu(hm, act, 1000, flags);\r
+            return;\r
+        }\r
+\r
+        mii.fMask = 0;\r
+\r
         if(act->state & KHUI_ACTIONSTATE_DISABLED) {\r
             mii.fMask |= MIIM_STATE;\r
             mii.fState = MFS_DISABLED;\r
@@ -211,8 +234,8 @@ static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main) {
 \r
     act = def->items;\r
     i = 0;\r
-    while((def->n_items == -1 && act->action != KHUI_MENU_END) ||\r
-          (def->n_items >= 0 && i < (int) def->n_items)) {\r
+    while((!(def->state & KHUI_MENUSTATE_ALLOCD) && act->action != KHUI_MENU_END) ||\r
+          ((def->state & KHUI_MENUSTATE_ALLOCD) && i < (int) def->n_items)) {\r
         add_action_to_menu(hm,khui_find_action(act->action),i,act->flags);\r
         act++; i++;\r
     }\r
@@ -392,12 +415,15 @@ LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam) {
 \r
         id = LOWORD(wParam);\r
         act = khui_find_action(id);\r
-        if(act == NULL || act->is_tooltip == 0)\r
+        if(act == NULL || (act->is_tooltip == 0 && act->tooltip == NULL))\r
             khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL);\r
         else {\r
-            LoadString(khm_hInstance, \r
-                       act->is_tooltip, \r
-                       buf, ARRAYLENGTH(buf));\r
+            if (act->tooltip)\r
+                StringCbCopy(buf, sizeof(buf), act->tooltip);\r
+            else\r
+                LoadString(khm_hInstance, \r
+                           act->is_tooltip, \r
+                           buf, ARRAYLENGTH(buf));\r
             khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf);\r
         }\r
     }\r
@@ -607,9 +633,9 @@ void khm_menu_create_main(HWND parent) {
     khui_main_menu_toolbar = hwtb;\r
 \r
     SendMessage(hwtb,\r
-        TB_BUTTONSTRUCTSIZE,\r
-        (WPARAM) sizeof(TBBUTTON),\r
-        0);\r
+                TB_BUTTONSTRUCTSIZE,\r
+                (WPARAM) sizeof(TBBUTTON),\r
+                0);\r
 \r
     for(i=0; i<nmm; i++) {\r
         khui_add_action_to_toolbar(hwtb, \r
@@ -623,7 +649,7 @@ void khm_menu_create_main(HWND parent) {
     SendMessage(hwtb,\r
                 TB_AUTOSIZE,\r
                 0,0);\r
-\r
+    \r
     SendMessage(hwtb,\r
                 TB_GETMAXSIZE,\r
                 0,\r
index 1e00c6d2a1766b482f7b79824f0e874f4609e357..84a580ce07b21d224eacbec4344e5a75b01fc9db 100644 (file)
@@ -43,7 +43,7 @@ void
 khm_set_dialog_result(HWND hwnd, LRESULT lr) {\r
 #pragma warning(push)\r
 #pragma warning(disable: 4244)\r
-    SetWindowLongPtr(hwnd, DWL_MSGRESULT, lr);\r
+    SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr);\r
 #pragma warning(pop)\r
 }\r
 \r
@@ -70,12 +70,113 @@ mw_restart_refresh_timer(HWND hwnd) {
     SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL);\r
 }\r
 \r
-LRESULT CALLBACK khm_main_wnd_proc(\r
-    HWND hwnd,\r
-    UINT uMsg,\r
-    WPARAM wParam,\r
-    LPARAM lParam\r
-    ) \r
+khm_int32 KHMAPI\r
+mw_select_cred(khm_handle cred, void * rock) {\r
+    if (cred)\r
+        kcdb_cred_set_flags(cred,\r
+                            KCDB_CRED_FLAG_SELECTED,\r
+                            KCDB_CRED_FLAG_SELECTED);\r
+\r
+    return KHM_ERROR_SUCCESS;\r
+}\r
+\r
+/* perform shutdown operations */\r
+static void\r
+khm_pre_shutdown(void) {\r
+    khm_handle csp_cw = NULL;\r
+    khm_handle credset = NULL;\r
+    khm_int32 t;\r
+    khm_size s;\r
+\r
+    /* Check if we should destroy all credentials on exit... */\r
+\r
+    if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw)))\r
+        return;\r
+\r
+    if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) ||\r
+        !t)\r
+        goto _cleanup;\r
+\r
+    if (KHM_FAILED(kcdb_credset_create(&credset)))\r
+        goto _cleanup;\r
+\r
+    if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL,\r
+                                        KCDB_TYPE_INVALID)))\r
+        goto _cleanup;\r
+\r
+    if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) ||\r
+        s == 0)\r
+        goto _cleanup;\r
+\r
+    kcdb_credset_apply(credset, mw_select_cred, NULL);\r
+\r
+    khui_context_set(KHUI_SCOPE_GROUP,\r
+                     NULL,\r
+                     KCDB_CREDTYPE_INVALID,\r
+                     NULL,\r
+                     NULL,\r
+                     0,\r
+                     credset);\r
+\r
+    khm_cred_destroy_creds(TRUE, TRUE);\r
+\r
+ _cleanup:\r
+\r
+    if (credset)\r
+        kcdb_credset_delete(credset);\r
+\r
+    if (csp_cw)\r
+        khc_close_space(csp_cw);\r
+}\r
+\r
+void\r
+khm_process_query_app_ver(khm_query_app_version * papp_ver) {\r
+\r
+    if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC)\r
+        return;\r
+\r
+    papp_ver->ver_remote = app_version;\r
+\r
+    /* the remote instance has requested swapping in.  we check the\r
+       version numbers and if the remote instance is newer than us,\r
+       then we exit and let the remote instance take over. */\r
+    if (papp_ver->request_swap) {\r
+        khm_version ver_caller = papp_ver->ver_caller;\r
+\r
+        if (ver_caller.major >   app_version.major ||\r
+\r
+            (ver_caller.major == app_version.major &&\r
+             ver_caller.minor >  app_version.minor) ||\r
+\r
+            (ver_caller.major == app_version.major &&\r
+             ver_caller.minor == app_version.minor &&\r
+             ver_caller.aux >    app_version.aux) ||\r
+\r
+            (ver_caller.major == app_version.major &&\r
+             ver_caller.minor == app_version.minor &&\r
+             ver_caller.aux ==   app_version.aux &&\r
+             ver_caller.patch >  app_version.patch)) {\r
+\r
+            papp_ver->request_swap = TRUE;\r
+\r
+            if (khm_hwnd_main)\r
+                DestroyWindow(khm_hwnd_main);\r
+\r
+        } else {\r
+\r
+            papp_ver->request_swap = FALSE;\r
+\r
+        }\r
+    }\r
+\r
+    papp_ver->code = KHM_ERROR_SUCCESS;\r
+}\r
+\r
+LRESULT CALLBACK \r
+khm_main_wnd_proc(HWND hwnd,\r
+                  UINT uMsg,\r
+                  WPARAM wParam,\r
+                  LPARAM lParam) \r
 {\r
     LPNMHDR lpnm;\r
 \r
@@ -92,6 +193,7 @@ LRESULT CALLBACK khm_main_wnd_proc(
         break;\r
 \r
     case WM_DESTROY:\r
+        khm_pre_shutdown();\r
         kmq_unsubscribe_hwnd(KMSG_ACT, hwnd);\r
         kmq_unsubscribe_hwnd(KMSG_CRED, hwnd);\r
         HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);\r
@@ -136,7 +238,7 @@ LRESULT CALLBACK khm_main_wnd_proc(
             return 0;\r
 \r
         case KHUI_ACTION_DESTROY_CRED:\r
-            khm_cred_destroy_creds();\r
+            khm_cred_destroy_creds(FALSE, FALSE);\r
             return 0;\r
 \r
         case KHUI_ACTION_SET_DEF_ID:\r
@@ -155,12 +257,16 @@ LRESULT CALLBACK khm_main_wnd_proc(
             khm_hide_main_window();\r
             break;\r
 \r
-        case KHUI_ACTION_OPT_KHIM:\r
-            khm_show_config_pane(NULL);\r
+        case KHUI_ACTION_OPT_KHIM: {\r
+            khui_config_node node = NULL;\r
+\r
+            khui_cfg_open(NULL, L"KhmGeneral", &node);\r
+            khm_show_config_pane(node);\r
+        }\r
             break;\r
 \r
         case KHUI_ACTION_OPT_IDENTS: {\r
-            khui_config_node node;\r
+            khui_config_node node = NULL;\r
 \r
             khui_cfg_open(NULL, L"KhmIdentities", &node);\r
             khm_show_config_pane(node);\r
@@ -168,7 +274,7 @@ LRESULT CALLBACK khm_main_wnd_proc(
             break;\r
 \r
         case KHUI_ACTION_OPT_NOTIF: {\r
-            khui_config_node node;\r
+            khui_config_node node = NULL;\r
 \r
             khui_cfg_open(NULL, L"KhmNotifications", &node);\r
             khm_show_config_pane(node);\r
@@ -176,7 +282,7 @@ LRESULT CALLBACK khm_main_wnd_proc(
             break;\r
 \r
         case KHUI_ACTION_OPT_PLUGINS: {\r
-            khui_config_node node;\r
+            khui_config_node node = NULL;\r
 \r
             khui_cfg_open(NULL, L"KhmPlugins", &node);\r
             khm_show_config_pane(node);\r
@@ -216,16 +322,27 @@ LRESULT CALLBACK khm_main_wnd_proc(
                 mm_last_hot_item = LOWORD(lParam);\r
             return khm_menu_activate(MENU_ACTIVATE_DEFAULT);\r
 \r
+        case KHUI_PACTION_ESC:\r
+            /* if esc is pressed while no menu is active, we close the\r
+               main window */\r
+            if (mm_last_hot_item == -1) {\r
+                khm_close_main_window();\r
+                return 0;\r
+            }\r
+\r
             /* generic, retargetting */\r
         case KHUI_PACTION_UP:\r
         case KHUI_PACTION_UP_TOGGLE:\r
         case KHUI_PACTION_UP_EXTEND:\r
+        case KHUI_PACTION_PGUP:\r
+        case KHUI_PACTION_PGUP_EXTEND:\r
         case KHUI_PACTION_DOWN:\r
         case KHUI_PACTION_DOWN_TOGGLE:\r
         case KHUI_PACTION_DOWN_EXTEND:\r
+        case KHUI_PACTION_PGDN:\r
+        case KHUI_PACTION_PGDN_EXTEND:\r
         case KHUI_PACTION_LEFT:\r
         case KHUI_PACTION_RIGHT:\r
-        case KHUI_PACTION_ESC:\r
         case KHUI_PACTION_ENTER:\r
             /* menu tracking */\r
             if(mm_last_hot_item != -1) {\r
@@ -251,16 +368,27 @@ LRESULT CALLBACK khm_main_wnd_proc(
             }\r
 \r
             /*FALLTHROUGH*/\r
-\r
         case KHUI_PACTION_DELETE:\r
 \r
         case KHUI_PACTION_SELALL:\r
         case KHUI_ACTION_LAYOUT_ID:\r
         case KHUI_ACTION_LAYOUT_TYPE:\r
         case KHUI_ACTION_LAYOUT_LOC:\r
+        case KHUI_ACTION_LAYOUT_CUST:\r
             /* otherwise fallthrough and bounce to the creds window */\r
             return SendMessage(khm_hwnd_main_cred, uMsg, \r
                                wParam, lParam);\r
+\r
+        default:\r
+            /* handle custom actions here */\r
+            {\r
+                khui_action * act;\r
+\r
+                act = khui_find_action(LOWORD(wParam));\r
+                if (act && act->listener) {\r
+                    kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL);\r
+                }\r
+            }\r
         }\r
         break;              /* WM_COMMAND */\r
 \r
@@ -271,34 +399,7 @@ LRESULT CALLBACK khm_main_wnd_proc(
             return 0;\r
 \r
         case SC_CLOSE:\r
-            {\r
-                khm_handle csp_cw;\r
-                BOOL keep_running = FALSE;\r
-\r
-                if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",\r
-                                                 KHM_PERM_READ, &csp_cw))) {\r
-                    khm_int32 t;\r
-\r
-                    if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", \r
-                                                     &t)))\r
-                        keep_running = t;\r
-#ifdef DEBUG\r
-                    else\r
-                        assert(FALSE);\r
-#endif\r
-\r
-                    khc_close_space(csp_cw);\r
-                }\r
-#ifdef DEBUG\r
-                else\r
-                    assert(FALSE);\r
-#endif\r
-\r
-                if (keep_running)\r
-                    khm_hide_main_window();\r
-                else\r
-                    DestroyWindow(hwnd);\r
-            }\r
+            khm_close_main_window();\r
             return 0;\r
         }\r
         break;\r
@@ -416,6 +517,27 @@ LRESULT CALLBACK khm_main_wnd_proc(
             } else if (m->type == KMSG_ACT &&\r
                        m->subtype == KMSG_ACT_CONTINUE_CMDLINE) {\r
                 khm_cred_process_commandline();\r
+            } else if (m->type == KMSG_ACT &&\r
+                       m->subtype == KMSG_ACT_SYNC_CFG) {\r
+                khm_refresh_config();\r
+            } else if (m->type == KMSG_ACT &&\r
+                       m->subtype == KMSG_ACT_ACTIVATE) {\r
+                /* some custom action fired */\r
+\r
+                khm_int32 action;\r
+                khui_action * paction;\r
+\r
+                action = m->uparam;\r
+                paction = khui_find_action(action);\r
+                if (paction && paction->data == (void *) CFGACTION_MAGIC) {\r
+                    /* a custom configuration needs to be invoked */\r
+                    khui_config_node node;\r
+\r
+                    if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) {\r
+                        khm_show_config_pane(node);\r
+                        khui_cfg_release(node);\r
+                    }\r
+                }\r
             } else if (m->type == KMSG_CRED &&\r
                   m->subtype == KMSG_CRED_REFRESH) {\r
                 mw_restart_refresh_timer(hwnd);\r
@@ -466,20 +588,49 @@ LRESULT CALLBACK khm_main_wnd_proc(
             khm_cred_begin_commandline();\r
         }\r
         break;\r
+\r
+    case WM_KHUI_QUERY_APP_VERSION:\r
+        {\r
+            HANDLE hmap;\r
+            void * xfer;\r
+            wchar_t mapname[256];\r
+\r
+            StringCbPrintf(mapname, sizeof(mapname),\r
+                           QUERY_APP_VER_MAP_FMT, (DWORD) lParam);\r
+\r
+            hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,\r
+                                   FALSE, mapname);\r
+\r
+            if (hmap == NULL)\r
+                return 1;\r
+\r
+            xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,\r
+                                 sizeof(khm_query_app_version));\r
+            \r
+            if (xfer) {\r
+                khm_process_query_app_ver((khm_query_app_version *) xfer);\r
+\r
+                UnmapViewOfFile(xfer);\r
+            }\r
+\r
+            CloseHandle(hmap);\r
+        }\r
+        break;\r
+\r
     }\r
     return DefWindowProc(hwnd,uMsg,wParam,lParam);\r
 }\r
 \r
-LRESULT CALLBACK khm_null_wnd_proc(\r
-    HWND hwnd,\r
-    UINT uMsg,\r
-    WPARAM wParam,\r
-    LPARAM lParam\r
-    ) {\r
+LRESULT CALLBACK \r
+khm_null_wnd_proc(HWND hwnd,\r
+                  UINT uMsg,\r
+                  WPARAM wParam,\r
+                  LPARAM lParam) {\r
     return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
 }\r
 \r
-LRESULT khm_rebar_notify(LPNMHDR lpnm) {\r
+LRESULT \r
+khm_rebar_notify(LPNMHDR lpnm) {\r
     switch(lpnm->code) {\r
 #if (_WIN32_WINNT >= 0x0501)\r
     case RBN_AUTOBREAK:\r
@@ -508,7 +659,8 @@ LRESULT khm_rebar_notify(LPNMHDR lpnm) {
     return 1;\r
 }\r
 \r
-void khm_create_main_window_controls(HWND hwnd_main) {\r
+void \r
+khm_create_main_window_controls(HWND hwnd_main) {\r
     REBARINFO rbi;\r
     HWND hwRebar;\r
 \r
@@ -552,7 +704,8 @@ void khm_create_main_window_controls(HWND hwnd_main) {
     khm_hwnd_main_cred = khm_create_credwnd(hwnd_main);\r
 }\r
 \r
-void khm_create_main_window(void) {\r
+void \r
+khm_create_main_window(void) {\r
     wchar_t buf[1024];\r
     khm_handle csp_cw = NULL;\r
     khm_handle csp_mw = NULL;\r
@@ -615,9 +768,11 @@ void khm_create_main_window(void) {
                        NULL,\r
                        NULL);\r
 \r
+    khui_set_main_window(khm_hwnd_main);\r
 }\r
 \r
-void khm_show_main_window(void) {\r
+void \r
+khm_show_main_window(void) {\r
 \r
     if (khm_nCmdShow == SW_RESTORE) {\r
         HWND hw;\r
@@ -639,7 +794,39 @@ void khm_show_main_window(void) {
     khm_nCmdShow = SW_RESTORE;\r
 }\r
 \r
-void khm_hide_main_window(void) {\r
+void \r
+khm_close_main_window(void) {\r
+    khm_handle csp_cw;\r
+    BOOL keep_running = FALSE;\r
+\r
+    if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow",\r
+                                     KHM_PERM_READ, &csp_cw))) {\r
+        khm_int32 t;\r
+\r
+        if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", \r
+                                         &t))) {\r
+            keep_running = t;\r
+        } else {\r
+#ifdef DEBUG\r
+            assert(FALSE);\r
+#endif\r
+        }\r
+\r
+        khc_close_space(csp_cw);\r
+    } else {\r
+#ifdef DEBUG\r
+        assert(FALSE);\r
+#endif\r
+    }\r
+\r
+    if (keep_running)\r
+        khm_hide_main_window();\r
+    else\r
+        DestroyWindow(khm_hwnd_main);\r
+}\r
+\r
+void \r
+khm_hide_main_window(void) {\r
     khm_handle csp_notices = NULL;\r
     khm_int32 show_warning = FALSE;\r
 \r
@@ -674,11 +861,13 @@ void khm_hide_main_window(void) {
     ShowWindow(khm_hwnd_main, SW_HIDE);\r
 }\r
 \r
-BOOL khm_is_main_window_visible(void) {\r
+BOOL \r
+khm_is_main_window_visible(void) {\r
     return IsWindowVisible(khm_hwnd_main);\r
 }\r
 \r
-BOOL khm_is_main_window_active(void) {\r
+BOOL \r
+khm_is_main_window_active(void) {\r
     if (!IsWindowVisible(khm_hwnd_main))\r
         return FALSE;\r
     if (GetForegroundWindow() == khm_hwnd_main)\r
@@ -686,7 +875,8 @@ BOOL khm_is_main_window_active(void) {
     return khm_is_dialog_active();\r
 }\r
 \r
-void khm_register_main_wnd_class(void) {\r
+void \r
+khm_register_main_wnd_class(void) {\r
     WNDCLASSEX wc;\r
 \r
     wc.cbSize = sizeof(WNDCLASSEX);\r
@@ -704,7 +894,6 @@ void khm_register_main_wnd_class(void) {
 \r
     khm_null_window_class = RegisterClassEx(&wc);\r
 \r
-\r
     wc.cbSize = sizeof(WNDCLASSEX);\r
     wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;\r
     wc.lpfnWndProc = khm_main_wnd_proc;\r
@@ -721,7 +910,8 @@ void khm_register_main_wnd_class(void) {
     khm_main_window_class = RegisterClassEx(&wc);\r
 }\r
 \r
-void khm_unregister_main_wnd_class(void) {\r
+void \r
+khm_unregister_main_wnd_class(void) {\r
     UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance);\r
     UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance);\r
 }\r
index 95b28b73343f47efb1d10d4d88316683132cd9ce..526248b1d2a9fa35dd5d6d789f17ebe5084ea54f 100644 (file)
@@ -39,6 +39,7 @@ void khm_unregister_main_wnd_class(void);
 void khm_create_main_window_controls(HWND);\r
 void khm_create_main_window(void);\r
 void khm_show_main_window(void);\r
+void khm_close_main_window(void);\r
 void khm_hide_main_window(void);\r
 BOOL khm_is_main_window_visible(void);\r
 BOOL khm_is_main_window_active(void);\r
@@ -54,7 +55,9 @@ khm_main_wnd_proc(HWND hwnd,
                   LPARAM lParam);\r
 \r
 #define WM_KHUI_ASSIGN_COMMANDLINE       32808\r
+#define WM_KHUI_QUERY_APP_VERSION        32809\r
 \r
 #define COMMANDLINE_MAP_FMT              L"Local\\NetIDMgr_Cmdline_%lu"\r
+#define QUERY_APP_VER_MAP_FMT            L"Local\\NetIDMgr_QueryVer_%lu"\r
 \r
 #endif\r
diff --git a/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 b/src/windows/identity/ui/netidmgr.manifest.amd64.vc7
new file mode 100644 (file)
index 0000000..0db331b
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+    version="1.0.0.0"
+    processorArchitecture="amd64"
+    name="MIT.NetIDMgr.UI"
+    type="win32"
+/>
+<description>Khimaira Credentials Manager</description>
+<dependency>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.Windows.Common-Controls"
+            version="6.0.0.0"
+            processorArchitecture="amd64"
+            publicKeyToken="6595b64144ccf1df"
+            language="*"
+        />
+    </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug b/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug
new file mode 100644 (file)
index 0000000..0db331b
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+    version="1.0.0.0"
+    processorArchitecture="amd64"
+    name="MIT.NetIDMgr.UI"
+    type="win32"
+/>
+<description>Khimaira Credentials Manager</description>
+<dependency>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.Windows.Common-Controls"
+            version="6.0.0.0"
+            processorArchitecture="amd64"
+            publicKeyToken="6595b64144ccf1df"
+            language="*"
+        />
+    </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 b/src/windows/identity/ui/netidmgr.manifest.amd64.vc8
new file mode 100644 (file)
index 0000000..6fb1e8d
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+    version="1.0.0.0"
+    processorArchitecture="amd64"
+    name="MIT.NetIDMgr.UI"
+    type="win32"
+/>
+<description>Khimaira Credentials Manager</description>
+<dependency>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.Windows.Common-Controls"
+            version="6.0.0.0"
+            processorArchitecture="amd64"
+            publicKeyToken="6595b64144ccf1df"
+            language="*"
+        />
+    </dependentAssembly>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.VC80.DebugCRT"
+            version="8.0.50215.4652"
+            processorArchitecture="amd64"
+            publicKeyToken="1fc8b3b9a1e18e3b"
+        />
+    </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug b/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug
new file mode 100644 (file)
index 0000000..6fb1e8d
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+    version="1.0.0.0"
+    processorArchitecture="amd64"
+    name="MIT.NetIDMgr.UI"
+    type="win32"
+/>
+<description>Khimaira Credentials Manager</description>
+<dependency>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.Windows.Common-Controls"
+            version="6.0.0.0"
+            processorArchitecture="amd64"
+            publicKeyToken="6595b64144ccf1df"
+            language="*"
+        />
+    </dependentAssembly>
+    <dependentAssembly>
+        <assemblyIdentity
+            type="win32"
+            name="Microsoft.VC80.DebugCRT"
+            version="8.0.50215.4652"
+            processorArchitecture="amd64"
+            publicKeyToken="1fc8b3b9a1e18e3b"
+        />
+    </dependentAssembly>
+</dependency>
+</assembly>
index 619b79687ac2c5ae8c8ab5a072b3d9415fe49870..3730a3c6e25eb8804826e86d5c5656d1b051dcf3 100644 (file)
@@ -899,7 +899,7 @@ nc_handle_wm_command(HWND hwnd,
         switch(LOWORD(wParam)) {\r
 \r
         case IDOK:\r
-            d->nc->result = KHUI_NC_RESULT_GET_CREDS;\r
+            d->nc->result = KHUI_NC_RESULT_PROCESS;\r
 \r
             /* fallthrough */\r
 \r
@@ -1178,7 +1178,7 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
                 if (d->nc->types[i]->dlg_proc == NULL) {\r
                     d->nc->types[i]->hwnd_panel = NULL;\r
                 } else {\r
-                    /* Create the dialog panel */ \r
+                    /* Create the dialog panel */\r
                     d->nc->types[i]->hwnd_panel = \r
                         CreateDialogParam(d->nc->types[i]->h_module,\r
                                           d->nc->types[i]->dlg_template,\r
index b7ac4626299073adde34c5879fd22ba9f926ce98..cde643ab278ad9eff5b00b181308d39a800da27e 100644 (file)
@@ -51,6 +51,8 @@ HWND hwnd_notifier = NULL;
 \r
 BOOL notifier_ready = FALSE;\r
 \r
+khm_boolean notifier_modal_loop = FALSE;\r
+\r
 khui_alert * current_alert = NULL;\r
 \r
 khui_alert * alert_queue[KHUI_ALERT_QUEUE_MAX];\r
@@ -184,6 +186,23 @@ notifier_wnd_proc(HWND hwnd,
                     }\r
                 }\r
                 break;\r
+\r
+            case KMSG_ALERT_SHOW_MODAL:\r
+                {\r
+                    khui_alert * a;\r
+\r
+                    a = (khui_alert *) m->vparam;\r
+                    a->flags |= KHUI_ALERT_FLAG_MODAL;\r
+                    rv = alert_show(a);\r
+                    khui_alert_release(a);\r
+\r
+                    if (KHM_SUCCEEDED(rv)) {\r
+                        notifier_modal_loop = TRUE;\r
+\r
+                        khm_message_loop_int(&notifier_modal_loop);\r
+                    }\r
+                }\r
+                break;\r
             }\r
         } else if (m->type == KMSG_CRED &&\r
                    m->subtype == KMSG_CRED_ROOTDELTA) {\r
@@ -251,6 +270,7 @@ notifier_wnd_proc(HWND hwnd,
                 }\r
             }\r
             /* fallthrough */\r
+        case NIN_BALLOONHIDE:\r
         case NIN_BALLOONTIMEOUT:\r
             khm_notify_icon_change(KHERR_NONE);\r
             if (current_alert) {\r
@@ -259,6 +279,7 @@ notifier_wnd_proc(HWND hwnd,
             }\r
             break;\r
 #endif\r
+\r
         }\r
     } else if (uMsg == WM_TIMER) {\r
         if (wParam == KHUI_TRIGGER_TIMER_ID) {\r
@@ -445,7 +466,16 @@ alert_show_normal(khui_alert * a) {
         khui_alert_add_command(a, KHUI_PACTION_CLOSE);\r
     }\r
 \r
-    if (!is_alert_queue_empty()) {\r
+    /* if there are other alerts queued up, we should add a 'Next\r
+       alert...' button that when clicked, would show the next queued\r
+       alert.  However, we only do this if the current alert doesn't\r
+       actually require a command response.  Otherwise, clicking the\r
+       'next' button will be the equivalent of cancelling out of the\r
+       alert without selecting any of the commands. */\r
+    if (!is_alert_queue_empty() &&\r
+        a->n_alert_commands == 1 &&\r
+        a->alert_commands[0] == KHUI_PACTION_CLOSE) {\r
+\r
         khui_alert_add_command(a, KHUI_PACTION_NEXT);\r
     }\r
 \r
@@ -457,14 +487,15 @@ alert_show_normal(khui_alert * a) {
         CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,\r
                        MAKEINTATOM(atom_alerter),\r
                        title,\r
-                       WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN |\r
-                       WS_VISIBLE,\r
+                       WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,\r
                        0, 0, 300, 300, // bogus values\r
                        khm_hwnd_main,\r
                        (HMENU) NULL,\r
                        khm_hInstance,\r
                        (LPVOID) a);\r
 \r
+    ShowWindow(hwa, SW_SHOW);\r
+\r
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
@@ -491,8 +522,9 @@ alert_show(khui_alert * a) {
 \r
     /* depending on the state of the main window, we\r
        need to either show a window or a balloon */\r
-    if(khm_is_main_window_active() &&\r
-       !(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON))\r
+    if ((a->flags & KHUI_ALERT_FLAG_MODAL) ||\r
+        (khm_is_main_window_active() &&\r
+         !(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON)))\r
         return alert_show_normal(a);\r
     else\r
         return alert_show_minimized(a);\r
@@ -676,7 +708,9 @@ alerter_wnd_proc(HWND hwnd,
                         CreateWindowEx(0,\r
                                        L"BUTTON",\r
                                        caption,\r
-                                       WS_VISIBLE | WS_CHILD,\r
+                                       WS_VISIBLE | WS_CHILD |\r
+                                       /* the first button is the default */\r
+                                       ((i==0)? BS_DEFPUSHBUTTON: 0),\r
                                        x,y,width,height,\r
                                        hwnd,\r
                                        (HMENU)(INT_PTR) (action->cmd),\r
@@ -719,6 +753,8 @@ alerter_wnd_proc(HWND hwnd,
 \r
             khui_alert_lock(d->alert);\r
             d->alert->flags &= ~KHUI_ALERT_FLAG_DISPLAY_WINDOW;\r
+            if (d->alert->flags & KHUI_ALERT_FLAG_MODAL)\r
+                notifier_modal_loop = FALSE;\r
             khui_alert_unlock(d->alert);\r
 \r
             khui_alert_release(d->alert);\r
@@ -935,6 +971,8 @@ alerter_wnd_proc(HWND hwnd,
                              SWP_NOMOVE | SWP_NOOWNERZORDER |\r
                              SWP_NOZORDER);\r
 \r
+                InvalidateRect(hwnd, NULL, TRUE);\r
+\r
                 x = d->x_message;\r
                 y = d->dy_client - d->dy_bb;\r
                 width = d->dx_button;\r
index 04056566d138a93ddcfcca4a3aef3f6577627d3e..684f6c74a6d60492f8636bb6f0ab027ea08c7341 100644 (file)
@@ -137,7 +137,7 @@ reqdaemonwnd_proc(HWND hwnd,
                                                         sizeof(widname))))\r
                     continue;\r
                 else {\r
-                    lr = (result != KHUI_NC_RESULT_GET_CREDS);\r
+                    lr = (result != KHUI_NC_RESULT_PROCESS);\r
                     break;\r
                 }\r
             } while(TRUE);\r
index b8060c6a0171933ad9408dc03f6f3e8f880757a0..19396fb23999655dc5090554d72b1613425eff6b 100644 (file)
@@ -1,6 +1,6 @@
 //{{NO_DEPENDENCIES}}\r
 // Microsoft Visual C++ generated include file.\r
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc\r
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc\r
 //\r
 #define IDI_MAIN_APP                    104\r
 #define IDD_PROPPAGE_MEDIUM             106\r
 #define IDI_ICON4                       206\r
 #define IDI_APPICON_OK                  206\r
 #define IDS_PISTATE_FAILREG             207\r
+#define IDI_CFG_PLUGIN                  207\r
 #define IDS_PISTATE_FAILDIS             208\r
+#define IDI_CFG_PLUGIN_ERR              208\r
 #define IDS_PISTATE_FAILLOD             209\r
+#define IDI_CFG_PLUGIN_DIS              209\r
 #define IDS_PISTATE_PLACEHOLD           210\r
 #define IDS_PISTATE_REG                 211\r
 #define IDS_PISTATE_HOLD                212\r
 #define IDS_NC_ID_DEF                   230\r
 #define IDS_NC_ID_WDEF                  231\r
 #define IDS_NC_ID_NDEF                  232\r
+#define IDS_PACTION_YES                 233\r
+#define IDS_PACTION_NO                  234\r
+#define IDS_PACTION_YESALL              235\r
+#define IDS_PACTION_NOALL               236\r
+#define IDS_PACTION_KEEP                237\r
+#define IDS_PACTION_REMOVE              238\r
+#define IDS_PACTION_DISCARD             239\r
+#define IDS_CFG_IT_MOD                  240\r
+#define IDS_CFG_IT_APP                  241\r
+#define IDS_CFG_IT_NONE                 242\r
+#define IDS_CFG_NODESC                  243\r
+#define IDS_CFG_P_DELCNFT               244\r
+#define IDS_CFG_P_DELCNFM               245\r
+#define IDS_CFG_P_DELCNFS               246\r
+#define IDS_CFG_P_DELNDEP               247\r
+#define IDS_CFG_P_ENBCNFT               248\r
+#define IDS_CFG_P_ENBCNFM               249\r
+#define IDS_PISTATE_FAILINIT            250\r
+#define IDS_CFG_P_UNRCNFT               251\r
+#define IDS_CFG_P_UNRCNFM               252\r
+#define IDS_CFG_P_UNRCNFS               253\r
+#define IDS_ACTION_LAYOUT_CUST          254\r
 #define IDC_NC_USERNAME                 1007\r
 #define IDC_NC_PASSWORD                 1008\r
 #define IDC_NC_CREDTEXT_LABEL           1009\r
 #define IDC_LIST1                       1103\r
 #define IDC_MODULES                     1103\r
 #define IDC_PP_CONFIG                   1104\r
+#define IDC_CFG_UNREGISTER              1107\r
+#define IDC_CFG_VERSION                 1108\r
+#define IDC_CFG_ICON                    1109\r
+#define IDC_CFG_LOGTOFILE               1110\r
+#define IDC_CFG_LOGPATH                 1111\r
+#define IDC_NOTIF_HALFLIFE              1112\r
+#define IDC_CFG_DESTROYALL              1113\r
 #define IDA_ACTIVATE_MENU               40003\r
 #define IDA_UP                          40004\r
 #define IDA_DOWN                        40005\r
 // \r
 #ifdef APSTUDIO_INVOKED\r
 #ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        207\r
+#define _APS_NEXT_RESOURCE_VALUE        210\r
 #define _APS_NEXT_COMMAND_VALUE         40010\r
-#define _APS_NEXT_CONTROL_VALUE         1107\r
+#define _APS_NEXT_CONTROL_VALUE         1114\r
 #define _APS_NEXT_SYMED_VALUE           101\r
 #endif\r
 #endif\r
index 5d28e6a582e3fc936bdaa8861e566c3b99a53bb7..40464d5ad0d22154bc2cf69a1b55ead98207bc54 100644 (file)
 #include<khmapp.h>\r
 #include<assert.h>\r
 \r
+/* The minimum half time interval is 60 seconds*/\r
+#define TT_MIN_HALFLIFE_INTERVAL 60\r
+\r
+/* as above, in FILETIME units of 100ns */\r
+#define FT_MIN_HALFLIFE_INTERVAL (TT_MIN_HALFLIFE_INTERVAL * 10000000i64)\r
+\r
 /* in seconds */\r
 #if 0\r
 khm_int32 khui_timeout_warn = KHUI_DEF_TIMEOUT_WARN;\r
@@ -161,11 +167,11 @@ tmr_fire_timer(void) {
 \r
                     khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED;\r
                 }\r
-#ifdef DEBUG\r
                 else {\r
+#ifdef DEBUG\r
                     assert(FALSE);\r
-                }\r
 #endif\r
+                }\r
             }\r
         }\r
     }\r
@@ -323,6 +329,71 @@ tmr_find(khm_handle key, khui_timer_type type,
         return -1;\r
 }\r
 \r
+/* called with cs_timers held. */\r
+static FILETIME\r
+tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) {\r
+    FILETIME lifetime;\r
+    FILETIME current;\r
+    FILETIME ret;\r
+\r
+    khm_int64 ilife;\r
+    khm_int64 icurrent;\r
+    khm_int64 iexpire;\r
+\r
+    khm_int64 iret;\r
+\r
+    GetSystemTimeAsFileTime(&current);\r
+\r
+    /* wha?? */\r
+    if (CompareFileTime(issue, expire) >= 0)\r
+        return current;\r
+\r
+    lifetime = FtSub(expire, issue);\r
+    icurrent = FtToInt(&current);\r
+    iexpire = FtToInt(expire);\r
+\r
+    ilife = FtToInt(&lifetime);\r
+\r
+    while(ilife / 2 > FT_MIN_HALFLIFE_INTERVAL) {\r
+        ilife /= 2;\r
+\r
+        /* is this the next renewal time? */\r
+        if (iexpire - ilife > icurrent) {\r
+            if (idx >= 0 &&\r
+                khui_timers[idx].expire == iexpire - ilife &&\r
+                (khui_timers[idx].flags & KHUI_TE_FLAG_EXPIRED)) {\r
+\r
+                /* if this renewal time has already been triggered\r
+                   (note that when the timer fires, it also fires all\r
+                   events that are within a few seconds of the current\r
+                   time) then we need to set the alarm for the next\r
+                   slot down the line. */\r
+\r
+                continue;\r
+\r
+            } else {\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    iret = iexpire - ilife;\r
+\r
+    ret = IntToFt(iret);\r
+\r
+    /* if the previous renew timer had fired, we need to mark it as\r
+       not expired.  However, we leave it to the caller to update the\r
+       actual timer and mark it as not stale. */\r
+    if (idx >= 0 &&\r
+        khui_timers[idx].expire < (khm_ui_8) iret) {\r
+\r
+        khui_timers[idx].flags &= ~KHUI_TE_FLAG_EXPIRED;\r
+        khui_timers[idx].expire = iret;\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
 /* called with cs_timers held */\r
 static khm_int32 KHMAPI\r
 tmr_cred_apply_proc(khm_handle cred, void * rock) {\r
@@ -333,6 +404,8 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
     FILETIME ft_current;\r
     FILETIME ft_creinst;\r
     FILETIME ft_cred_expiry;\r
+    FILETIME ft_cred_issue;\r
+    FILETIME ft_issue;\r
     FILETIME ft;\r
     FILETIME fte;\r
     FILETIME ft_reinst;\r
@@ -347,7 +420,8 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
     cb = sizeof(ft_expiry);\r
     if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,\r
                                           NULL,\r
-                                          &ft_expiry, &cb)))\r
+                                          &ft_expiry, &cb))) {\r
+        cb = sizeof(ft_expiry);\r
         if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE,\r
                                           NULL,\r
                                           &ft_expiry, &cb))) {\r
@@ -355,6 +429,22 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
             kcdb_identity_release(ident);\r
             return KHM_ERROR_SUCCESS;\r
         }\r
+    }\r
+\r
+    cb = sizeof(ft_issue);\r
+    if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE,\r
+                                          NULL,\r
+                                          &ft_issue, &cb))) {\r
+        cb = sizeof(ft_issue);\r
+        if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,\r
+                                          NULL,\r
+                                          &ft_issue, &cb))) {\r
+            /* we don't really abandon the timer.  In this case, we\r
+               fall back to using the threshold value to set the\r
+               expiry timer. */\r
+            ZeroMemory(&ft_issue, sizeof(ft_issue));\r
+        }\r
+    }\r
 \r
     /* and the current time */\r
     GetSystemTimeAsFileTime(&ft_current);\r
@@ -383,6 +473,7 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
         khm_boolean do_warn = TRUE;\r
         khm_boolean do_crit = TRUE;\r
         khm_boolean do_renew = TRUE;\r
+        khm_boolean do_halflife = TRUE;\r
         khm_boolean renew_done = FALSE;\r
         khm_boolean monitor = TRUE;\r
         khm_int32 to_warn = KHUI_DEF_TIMEOUT_WARN;\r
@@ -423,6 +514,10 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
         if (KHM_SUCCEEDED(rv))\r
             do_renew = t;\r
 \r
+        rv = khc_read_int32(csp_id, L"RenewAtHalfLife", &t);\r
+        if (KHM_SUCCEEDED(rv))\r
+            do_halflife = t;\r
+\r
         rv = khc_read_int32(csp_id, L"WarnThreshold", &t);\r
         if (KHM_SUCCEEDED(rv))\r
             to_warn = t;\r
@@ -441,16 +536,21 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
             int prev;\r
 \r
             TimetToFileTimeInterval(to_renew, &ft);\r
-            fte = FtSub(&ft_expiry, &ft);\r
 \r
             prev =\r
                 tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0);\r
 \r
+            if (do_halflife)\r
+                fte = tmr_next_halflife_timeout(prev, &ft_issue, &ft_expiry);\r
+            else\r
+                fte = FtSub(&ft_expiry, &ft);\r
+\r
             /* we set off a renew notification immediately if the\r
                renew threshold has passed but a renew was never sent.\r
                This maybe because that NetIDMgr was started at the\r
                last minute, or because for some reason the renew timer\r
                could not be triggered earlier. */\r
+\r
             if (CompareFileTime(&fte, &ft_current) > 0 ||\r
                 prev == -1 ||\r
                 !(khui_timers[prev].flags & KHUI_TE_FLAG_EXPIRED)) {\r
@@ -462,14 +562,18 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
                            FtToInt(&fte), FtToInt(&ft), 0,\r
                            CompareFileTime(&fte,&ft_creinst) > 0);\r
                 renew_done = TRUE;\r
+\r
             } else {\r
+\r
                 /* special case.  If the renew timer was in the past\r
                    and it was expired, then we retain the record as\r
                    long as the credentials are around.  If the renewal\r
                    failed we don't want to automatically retry\r
                    everytime we check the timers. */\r
+\r
                 tmr_update(ident, KHUI_TTYPE_ID_RENEW,\r
                            FtToInt(&fte), FtToInt(&ft), 0, FALSE);\r
+\r
             }\r
         }\r
 \r
@@ -512,9 +616,21 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
                                       &cb)))\r
         goto _cleanup;\r
 \r
+    cb = sizeof(ft_cred_issue);\r
+    if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE,\r
+                                      NULL,\r
+                                      &ft_cred_issue,\r
+                                      &cb)))\r
+        goto _cleanup;\r
+\r
     TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft);\r
 \r
     {\r
+        /* if the credential has a longer lifetime than the identity,\r
+           or it expires within KHUI_TIMEEQ_ERROR seconds of the\r
+           identity, then we don't need to set any alerts for this\r
+           credential. */\r
+\r
         FILETIME ft_delta;\r
 \r
         ft_delta = FtSub(&ft_expiry, &ft_cred_expiry);\r
@@ -529,12 +645,12 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
 \r
         fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);\r
         if (CompareFileTime(&fte, &ft_current) > 0) {\r
-            tmr_update(cred, KHUI_TTYPE_CRED_WARN,\r
-                       FtToInt(&fte), \r
-                       khui_timers[idx].offset, 0,\r
-                       CompareFileTime(&fte, &ft_creinst) > 0);\r
-            kcdb_cred_hold(cred);\r
-        }\r
+           tmr_update(cred, KHUI_TTYPE_CRED_WARN,\r
+                      FtToInt(&fte), \r
+                      khui_timers[idx].offset, 0,\r
+                      CompareFileTime(&fte, &ft_creinst) > 0);\r
+           kcdb_cred_hold(cred);\r
+       }\r
     }\r
 \r
     if ((idx = tmr_find(ident, KHUI_TTYPE_ID_CRIT, 0, 0)) >= 0 &&\r
@@ -553,7 +669,9 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) {
     if ((idx = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0)) >= 0 &&\r
         !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) {\r
 \r
-        fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);\r
+        //fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset);\r
+        fte = tmr_next_halflife_timeout(idx, &ft_cred_issue, &ft_cred_expiry);\r
+\r
         if (CompareFileTime(&fte, &ft_current) > 0) {\r
             tmr_update(cred, KHUI_TTYPE_CRED_RENEW,\r
                        FtToInt(&fte),\r
@@ -648,14 +766,26 @@ khm_timer_refresh(HWND hwnd) {
 \r
     KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID);\r
 \r
+    /* When refreshing timers, we go through all of them and mark them\r
+       as stale.  Then we go through the credentials in the root\r
+       credential set and add or refresh the timers associated with\r
+       each identity and credential.  Once this is done, we remove the\r
+       timers that are still stale, since they are no longer in\r
+       use. */\r
+\r
     for (i=0; i < (int) khui_n_timers; i++) {\r
 #ifdef NOT_IMPLEMENTED_YET\r
         if (khui_timers[i].type == KHUI_TTYPE_BMSG ||\r
             khui_timers[i].type == KHUI_TTYPE_SMSG) {\r
             khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE;\r
-        } else\r
+        } else {\r
 #endif\r
+\r
             khui_timers[i].flags |= KHUI_TE_FLAG_STALE;\r
+\r
+#ifdef NOT_IMPLEMENTED_YET\r
+       }\r
+#endif\r
     }\r
 \r
     kcdb_credset_apply(NULL,\r
@@ -666,6 +796,10 @@ khm_timer_refresh(HWND hwnd) {
 \r
  _check_next_event:\r
 \r
+    /* Before we return, we should check if any timers are set to\r
+       expire right now.  If there are, we should fire the timer\r
+       before returning. */\r
+\r
     next_event = 0;\r
     for (i=0; i < (int) khui_n_timers; i++) {\r
         if (!(khui_timers[i].flags & KHUI_TE_FLAG_EXPIRED) &&\r
index 14057ddedb7a61b29dc804eeeda331e0e248424f..5c512bbac16362021476b7d945464a7fa05353e3 100644 (file)
@@ -6,7 +6,7 @@ CredWindow,KC_SPACE,0,Options for the credentials window
   AutoDetectNet,KC_INT32,1,Automatically detect network connectivity changes\r
   KeepRunning,KC_INT32,1,Keep running after closing Khimaira\r
   DefaultView,KC_STRING,ByIdentity,\r
-  ViewList,KC_STRING,"ByIdentity,ByLocation",\r
+  ViewList,KC_STRING,"ByIdentity,ByLocation,ByType",\r
   PaddingHorizontal,KC_INT32,4,\r
   PaddingVertical,KC_INT32,2,\r
   PaddingHeader,KC_INT32,16,\r
@@ -19,10 +19,13 @@ CredWindow,KC_SPACE,0,Options for the credentials window
   AllowCritical,KC_INT32,1,Boolean. Enables critical.\r
   AutoRenewThreshold,KC_INT32,600,In seconds\r
   AllowAutoRenew,KC_INT32,1,Boolean.\r
+  RenewAtHalfLife,KC_INT32,1,Boolean. Use half-life algorithm for renewals.\r
   DefaultAllowAutoRenew,KC_INT32,1,Default AllowAutoRenew value for new identities\r
   DefaultSticky,KC_INT32,0,Default Sticky value for new identities\r
   MaxThreshold,KC_INT32,86400,Max value for a threshold (1 day)\r
   MinThreshold,KC_INT32,10,Min value for a threshold (0)\r
+  LogToFile,KC_INT32,0,Boolean. If true logs trace events to a nidmdbg.log in the temp folder\r
+  DestroyCredsOnExit,KC_INT32,0,Boolean.  If true; all credentials will be destroyed when NetIDMgr exits.\r
   Windows,KC_SPACE,0,Window parameters\r
     _Schema,KC_SPACE,0,Schema\r
       Width,KC_INT32,0,\r
@@ -35,6 +38,33 @@ CredWindow,KC_SPACE,0,Options for the credentials window
   Windows,KC_ENDSPACE,0,\r
   Views,KC_SPACE,0,Preconfigured views for credentials\r
    Custom_0,KC_SPACE,0,First custom view.  Additional views have names of the form Custom_N\r
+    Description,KC_STRING,Custom view,\r
+    ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Name,TimeLeft",\r
+    Columns,KC_SPACE,0,Columns\r
+      _CWFlags,KC_SPACE,0,\r
+        Width,KC_INT32,20,\r
+        Flags,KC_INT32,112,\r
+      _CWFlags,KC_ENDSPACE,0,\r
+      IdentityName,KC_SPACE,0,\r
+        Width,KC_INT32,100,\r
+        SortIndex,KC_INT32,0,\r
+        Flags,KC_INT32,11,\r
+      IdentityName,KC_ENDSPACE,0\r
+      TypeName,KC_SPACE,0\r
+        Width,KC_INT32,100\r
+        SortIndex,KC_INT32,1\r
+        Flags,KC_INT32,11\r
+      TypeName,KC_ENDSPACE,0\r
+      Name,KC_SPACE,0\r
+        Width,KC_INT32,200\r
+        SortIndex,KC_INT32,2\r
+        Flags,KC_INT32,3\r
+      Name,KC_ENDSPACE,0\r
+      TimeLeft,KC_SPACE,0\r
+        Width,KC_INT32,200\r
+        Flags,KC_INT32,1\r
+      TimeLeft,KC_ENDSPACE,0\r
+    Columns,KC_ENDSPACE,0\r
    Custom_0,KC_ENDSPACE,0,\r
    ByIdentity,KC_SPACE,0,The default view\r
     Description,KC_STRING,View grouped by identity and credential type,\r
@@ -42,12 +72,8 @@ CredWindow,KC_SPACE,0,Options for the credentials window
     Columns,KC_SPACE,0,Columns\r
       _CWFlags,KC_SPACE,0,\r
         Width,KC_INT32,20,\r
-       Flags,KC_INT32,112,\r
+        Flags,KC_INT32,112,\r
       _CWFlags,KC_ENDSPACE,0,\r
-#      _CWTypeIcon,KC_SPACE,0,\r
-#        Width,KC_INT32,20,\r
-#      Flags,KC_INT32,112,\r
-#      _CWTypeIcon,KC_ENDSPACE,0,\r
       IdentityName,KC_SPACE,0,\r
         Width,KC_INT32,100,\r
         SortIndex,KC_INT32,0,\r
@@ -69,18 +95,43 @@ CredWindow,KC_SPACE,0,Options for the credentials window
       TimeLeft,KC_ENDSPACE,0\r
     Columns,KC_ENDSPACE,0\r
    ByIdentity,KC_ENDSPACE,0\r
+   ByType,KC_SPACE,0,The default view\r
+    Description,KC_STRING,View grouped by type and identity,\r
+    ColumnList,KC_STRING,"_CWFlags,TypeName,IdentityName,Name,TimeLeft",\r
+    Columns,KC_SPACE,0,Columns\r
+      _CWFlags,KC_SPACE,0,\r
+        Width,KC_INT32,20,\r
+        Flags,KC_INT32,112,\r
+      _CWFlags,KC_ENDSPACE,0,\r
+      TypeName,KC_SPACE,0\r
+        Width,KC_INT32,100\r
+        SortIndex,KC_INT32,0\r
+        Flags,KC_INT32,11\r
+      TypeName,KC_ENDSPACE,0\r
+      IdentityName,KC_SPACE,0,\r
+        Width,KC_INT32,100,\r
+        SortIndex,KC_INT32,1,\r
+        Flags,KC_INT32,11,\r
+      IdentityName,KC_ENDSPACE,0\r
+      Name,KC_SPACE,0\r
+        Width,KC_INT32,200\r
+        SortIndex,KC_INT32,2\r
+        Flags,KC_INT32,3\r
+      Name,KC_ENDSPACE,0\r
+      TimeLeft,KC_SPACE,0\r
+        Width,KC_INT32,200\r
+        Flags,KC_INT32,1\r
+      TimeLeft,KC_ENDSPACE,0\r
+    Columns,KC_ENDSPACE,0\r
+   ByType,KC_ENDSPACE,0\r
    ByLocation,KC_SPACE,0,View by location\r
     Description,KC_STRING,View grouped by location,\r
     ColumnList,KC_STRING,"_CWFlags,Location,IdentityName,TypeName,Name,TimeLeft",\r
     Columns,KC_SPACE,0,Columns\r
       _CWFlags,KC_SPACE,0,\r
         Width,KC_INT32,20,\r
-       Flags,KC_INT32,112,\r
+        Flags,KC_INT32,112,\r
       _CWFlags,KC_ENDSPACE,0,\r
-#      _CWTypeIcon,KC_SPACE,0,\r
-#        Width,KC_INT32,20,\r
-#      Flags,KC_INT32,112,\r
-#      _CWTypeIcon,KC_ENDSPACE,0,\r
       Location,KC_SPACE,0,\r
         Width,KC_INT32,100,\r
         SortIndex,KC_INT32,0,\r
index a97b37ba46044d7a4c9526a12ad8563f736469f8..f95e89bc82df464af0af8ee861d744bf12fb2dd1 100644 (file)
@@ -3,9 +3,13 @@ KHUI_PACTION_MENU,FVIRTKEY,VK_F10,KHUI_ACCEL_SCOPE_GLOBAL
 KHUI_PACTION_UP,FVIRTKEY,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_UP_EXTEND,FVIRTKEY|FSHIFT,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_UP_TOGGLE,FVIRTKEY|FCONTROL,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL\r
+KHUI_PACTION_PGUP,FVIRTKEY,VK_PRIOR,KHUI_ACCEL_SCOPE_GLOBAL\r
+KHUI_PACTION_PGUP_EXTEND,FVIRTKEY|FSHIFT,VK_PRIOR,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_DOWN,FVIRTKEY,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_DOWN_EXTEND,FVIRTKEY|FSHIFT,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_DOWN_TOGGLE,FVIRTKEY|FCONTROL,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL\r
+KHUI_PACTION_PGDN,FVIRTKEY,VK_NEXT,KHUI_ACCEL_SCOPE_GLOBAL\r
+KHUI_PACTION_PGDN_EXTEND,FVIRTKEY|FSHIFT,VK_NEXT,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_LEFT,FVIRTKEY,VK_LEFT,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_RIGHT,FVIRTKEY,VK_RIGHT,KHUI_ACCEL_SCOPE_GLOBAL\r
 KHUI_PACTION_ENTER,FVIRTKEY,VK_RETURN,KHUI_ACCEL_SCOPE_GLOBAL\r
index 5dc72e6102abeb25cf6644792f9a6be4ba1989aa..3be4f2e46277ac57284bd3b114be93164c161acc 100644 (file)
@@ -28,6 +28,7 @@ This file was autogenerated from src/ui/acceldef.cfg and src/ui/accel.csv.
 \r
 Do not modify directly.\r
 */\r
+#define NOEXPORT\r
 #include<khuidefs.h>\r
 \r
 khui_accel_def khui_accel_global[] = {\r
index b337eb8944e2269fb6cdbb6e767013e5af8869c1..4f68bbfa66e6829798ece9af5c3fad0b5302988e 100644 (file)
 #include<assert.h>\r
 \r
 khui_action_ref khui_main_menu[] = {\r
-    MENU_ACTION(KHUI_MENU_FILE),\r
-    MENU_ACTION(KHUI_MENU_CRED),\r
-    MENU_ACTION(KHUI_MENU_VIEW),\r
-    MENU_ACTION(KHUI_MENU_OPTIONS),\r
-    MENU_ACTION(KHUI_MENU_HELP),\r
+    MENU_SUBMENU(KHUI_MENU_FILE),\r
+    MENU_SUBMENU(KHUI_MENU_CRED),\r
+    MENU_SUBMENU(KHUI_MENU_VIEW),\r
+    MENU_SUBMENU(KHUI_MENU_OPTIONS),\r
+    MENU_SUBMENU(KHUI_MENU_HELP),\r
     MENU_END()\r
 };\r
 \r
@@ -53,7 +53,10 @@ khui_action_ref khui_menu_cred[] = {
     MENU_ACTION(KHUI_ACTION_DESTROY_CRED),\r
     MENU_SEP(),\r
     MENU_ACTION(KHUI_ACTION_SET_DEF_ID),\r
+#if 0\r
+    /* not implemented yet */\r
     MENU_ACTION(KHUI_ACTION_SET_SRCH_ID),\r
+#endif\r
     MENU_SEP(),\r
     MENU_ACTION(KHUI_ACTION_PASSWD_ID),\r
     MENU_END()\r
@@ -63,6 +66,7 @@ khui_action_ref khui_menu_layout[] = {
     MENU_ACTION(KHUI_ACTION_LAYOUT_ID),\r
     MENU_ACTION(KHUI_ACTION_LAYOUT_TYPE),\r
     MENU_ACTION(KHUI_ACTION_LAYOUT_LOC),\r
+    MENU_ACTION(KHUI_ACTION_LAYOUT_CUST),\r
     MENU_END()\r
 };\r
 \r
@@ -72,12 +76,18 @@ khui_action_ref khui_menu_toolbars[] = {
 };\r
 \r
 khui_action_ref khui_menu_view[] = {\r
-    MENU_ACTION(KHUI_ACTION_CHOOSE_COLS),\r
-    MENU_ACTION(KHUI_MENU_LAYOUT),\r
-    MENU_ACTION(KHUI_MENU_TOOLBARS),\r
+    MENU_SUBMENU(KHUI_MENU_COLUMNS),\r
+    MENU_SUBMENU(KHUI_MENU_LAYOUT),\r
+#if 0\r
+    /* not implemented yet */\r
+    MENU_SUBMENU(KHUI_MENU_TOOLBARS),\r
+#endif\r
     MENU_SEP(),\r
+#if 0\r
+    /* not implemented yet */\r
     MENU_ACTION(KHUI_ACTION_DEBUG_WINDOW),\r
     MENU_SEP(),\r
+#endif\r
     MENU_ACTION(KHUI_ACTION_VIEW_REFRESH),\r
     MENU_END()\r
 };\r
@@ -87,6 +97,7 @@ khui_action_ref khui_menu_options[] = {
     MENU_ACTION(KHUI_ACTION_OPT_IDENTS),\r
     MENU_ACTION(KHUI_ACTION_OPT_NOTIF),\r
     MENU_ACTION(KHUI_ACTION_OPT_PLUGINS),\r
+    MENU_SEP(),\r
     MENU_END()\r
 };\r
 \r
@@ -157,6 +168,16 @@ khui_action_ref khui_menu_ico_ctx_normal[] = {
     MENU_END()\r
 };\r
 \r
+khui_action_ref khui_menu_cwheader_ctx[] = {\r
+    MENU_SUBMENU(KHUI_MENU_COLUMNS),\r
+    MENU_SUBMENU(KHUI_MENU_LAYOUT),\r
+    MENU_END()\r
+};\r
+\r
+khui_action_ref khui_menu_columns[] = {\r
+    MENU_END()\r
+};\r
+\r
 khui_action_ref khui_pmenu_tok_sel[] = {\r
     MENU_ACTION(KHUI_ACTION_RENEW_CRED),\r
     MENU_ACTION(KHUI_ACTION_DESTROY_CRED),\r
@@ -171,23 +192,25 @@ khui_action_ref khui_pmenu_id_sel[] = {
 \r
 /* all stock menus and toolbars */\r
 khui_menu_def khui_all_menus[] = {\r
-    CONSTMENU(KHUI_MENU_MAIN, KHUI_MENUSTATE_CONSTANT, khui_main_menu),\r
-    CONSTMENU(KHUI_MENU_FILE, KHUI_MENUSTATE_CONSTANT, khui_menu_file),\r
-    CONSTMENU(KHUI_MENU_CRED, KHUI_MENUSTATE_CONSTANT, khui_menu_cred),\r
-    CONSTMENU(KHUI_MENU_VIEW, KHUI_MENUSTATE_CONSTANT, khui_menu_view),\r
-    CONSTMENU(KHUI_MENU_LAYOUT, KHUI_MENUSTATE_CONSTANT, khui_menu_layout),\r
-    CONSTMENU(KHUI_MENU_TOOLBARS, KHUI_MENUSTATE_CONSTANT, khui_menu_toolbars),\r
-    CONSTMENU(KHUI_MENU_OPTIONS, KHUI_MENUSTATE_CONSTANT, khui_menu_options),\r
-    CONSTMENU(KHUI_MENU_HELP, KHUI_MENUSTATE_CONSTANT, khui_menu_help),\r
+    CONSTMENU(KHUI_MENU_MAIN, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_main_menu),\r
+    CONSTMENU(KHUI_MENU_FILE, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_file),\r
+    CONSTMENU(KHUI_MENU_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_cred),\r
+    CONSTMENU(KHUI_MENU_VIEW, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_view),\r
+    CONSTMENU(KHUI_MENU_LAYOUT, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_layout),\r
+    CONSTMENU(KHUI_MENU_TOOLBARS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_toolbars),\r
+    CONSTMENU(KHUI_MENU_OPTIONS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_options),\r
+    CONSTMENU(KHUI_MENU_HELP, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_help),\r
+    CONSTMENU(KHUI_MENU_COLUMNS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_columns),\r
 \r
     /* toolbars */\r
-    CONSTMENU(KHUI_TOOLBAR_STANDARD, KHUI_MENUSTATE_CONSTANT, khui_toolbar_standard),\r
+    CONSTMENU(KHUI_TOOLBAR_STANDARD, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_toolbar_standard),\r
 \r
     /* context menus */\r
     CONSTMENU(KHUI_MENU_IDENT_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_ident_ctx),\r
     CONSTMENU(KHUI_MENU_TOK_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_tok_ctx),\r
     CONSTMENU(KHUI_MENU_ICO_CTX_MIN, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_min),\r
     CONSTMENU(KHUI_MENU_ICO_CTX_NORMAL, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_normal),\r
+    CONSTMENU(KHUI_MENU_CWHEADER_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_cwheader_ctx),\r
 \r
     /* pseudo menus */\r
     CONSTMENU(KHUI_PMENU_TOK_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_tok_sel),\r
@@ -195,8 +218,22 @@ khui_menu_def khui_all_menus[] = {
 };\r
 \r
 int khui_n_all_menus = sizeof(khui_all_menus) / sizeof(khui_menu_def);\r
+khui_menu_def ** khui_cust_menus = NULL;\r
+int khui_nc_cust_menus = 0;\r
+int khui_n_cust_menus = 0;\r
 CRITICAL_SECTION cs_actions;\r
 \r
+#define CACT_NC_ALLOC 32\r
+\r
+khui_action ** khui_cust_actions = NULL;\r
+int khui_nc_cust_actions = 0;\r
+int khui_n_cust_actions = 0;\r
+\r
+HWND khui_hwnd_main;                   /* main window, for notifying\r
+                                           action launches and\r
+                                           dispatching messages to the\r
+                                           application. */\r
+\r
 KHMEXP void KHMAPI \r
 khui_init_actions(void) {\r
     InitializeCriticalSection(&cs_actions);\r
@@ -207,25 +244,208 @@ khui_exit_actions(void) {
     DeleteCriticalSection(&cs_actions);\r
 }\r
 \r
+KHMEXP khm_int32 KHMAPI\r
+khui_action_create(const wchar_t * name,\r
+                   const wchar_t * caption,\r
+                   const wchar_t * tooltip,\r
+                   void * userdata,\r
+                   khm_int32 type,\r
+                   khm_handle hsub) {\r
+    khui_action * act;\r
+    khm_int32 action = 0;\r
+    int i;\r
+    size_t s;\r
+\r
+    if (!caption ||\r
+        FAILED(StringCchLength(caption, KHUI_MAXCCH_SHORT_DESC, &s)) ||\r
+        (tooltip && FAILED(StringCchLength(tooltip, KHUI_MAXCCH_SHORT_DESC, &s))) ||\r
+        (type != KHUI_ACTIONTYPE_TRIGGER && type != KHUI_ACTIONTYPE_TOGGLE)) {\r
+        return 0;\r
+    }\r
+\r
+    EnterCriticalSection(&cs_actions);\r
+    if (name && (act = khui_find_named_action(name))) {\r
+        /* named action already exists */\r
+        action = act->cmd;\r
+        goto _done;\r
+    }\r
+\r
+    for (i=0; i < khui_n_cust_actions; i++) {\r
+        if (khui_cust_actions[i] == NULL ||\r
+            (khui_cust_actions[i]->state & KHUI_ACTIONSTATE_DELETED))\r
+            break;\r
+    }\r
+\r
+    if (i >= khui_n_cust_actions &&\r
+        (khui_cust_actions == NULL ||\r
+         khui_n_cust_actions + 1 > khui_nc_cust_actions)) {\r
+\r
+        khui_nc_cust_actions = UBOUNDSS(khui_n_cust_actions + 1,\r
+                                        CACT_NC_ALLOC,\r
+                                        CACT_NC_ALLOC);\r
+#ifdef DEBUG\r
+        assert(khui_nc_cust_actions > khui_n_cust_actions + 1);\r
+#endif\r
+        khui_cust_actions = PREALLOC(khui_cust_actions,\r
+                                     sizeof(*khui_cust_actions) * khui_nc_cust_actions);\r
+#ifdef DEBUG\r
+        assert(khui_cust_actions);\r
+#endif\r
+    }\r
+\r
+    if (i >= khui_n_cust_actions) {\r
+        i = khui_n_cust_actions ++;\r
+        act = PMALLOC(sizeof(khui_action));\r
+    } else {\r
+        act = khui_cust_actions[i];\r
+        if (act == NULL)\r
+            act = PMALLOC(sizeof(khui_action));\r
+    }\r
+\r
+#ifdef DEBUG\r
+    assert(act);\r
+#endif\r
+\r
+    khui_cust_actions[i] = act;\r
+\r
+    ZeroMemory(act, sizeof(*act));\r
+\r
+    act->cmd = KHUI_USERACTION_BASE + i;\r
+    act->type = type;\r
+    act->name = (name? PWCSDUP(name) : 0);\r
+    act->caption = PWCSDUP(caption);\r
+    act->tooltip = (tooltip? PWCSDUP(tooltip) : 0);\r
+    act->listener = hsub;\r
+    act->data = userdata;\r
+    act->state = 0;\r
+\r
+    action = act->cmd;\r
+\r
+ _done:\r
+    LeaveCriticalSection(&cs_actions);\r
+\r
+    if (action)\r
+        kmq_post_message(KMSG_ACT, KMSG_ACT_NEW, action, NULL);\r
+\r
+    return action;\r
+}\r
+\r
+KHMEXP void * KHMAPI\r
+khui_action_get_data(khm_int32 action) {\r
+    khui_action * act;\r
+\r
+    act = khui_find_action(action);\r
+\r
+    if (act == NULL)\r
+        return NULL;\r
+    else\r
+        return act->data;\r
+}\r
+\r
+KHMEXP void KHMAPI\r
+khui_action_delete(khm_int32 action) {\r
+    khui_action * act;\r
+\r
+    act = khui_find_action(action);\r
+\r
+    if (act == NULL)\r
+        return;\r
+\r
+    /* for the moment, even when the action is deleted, we don't free\r
+       up the block of memory used by the khui_action structure.  When\r
+       a new action is created, it will reuse deleted action\r
+       structures. */\r
+    EnterCriticalSection(&cs_actions);\r
+    act->state |= KHUI_ACTIONSTATE_DELETED;\r
+    if (act->name)\r
+        PFREE(act->name);\r
+    if (act->caption)\r
+        PFREE(act->caption);\r
+    if (act->tooltip)\r
+        PFREE(act->tooltip);\r
+    if (act->listener)\r
+        kmq_delete_subscription(act->listener);\r
+    act->name = NULL;\r
+    act->caption = NULL;\r
+    act->tooltip = NULL;\r
+    act->listener = NULL;\r
+    LeaveCriticalSection(&cs_actions);\r
+\r
+    kmq_post_message(KMSG_ACT, KMSG_ACT_DELETE, action, NULL);\r
+}\r
+\r
 #define MENU_NC_ITEMS 8\r
 \r
 KHMEXP khui_menu_def * KHMAPI \r
-khui_menu_create(int cmd)\r
+khui_menu_create(khm_int32 action)\r
 {\r
     khui_menu_def * d;\r
 \r
     d = PMALLOC(sizeof(*d));\r
     ZeroMemory(d, sizeof(*d));\r
 \r
-    d->cmd = cmd;\r
+    d->cmd = action;\r
     d->nc_items = MENU_NC_ITEMS;\r
-    d->items = PMALLOC(sizeof(*(d->items)) *  d->nc_items);\r
+    d->items = PMALLOC(sizeof(*(d->items)) * d->nc_items);\r
 \r
     d->state = KHUI_MENUSTATE_ALLOCD;\r
 \r
+    if (action) {\r
+        int i;\r
+        EnterCriticalSection(&cs_actions);\r
+\r
+        for (i=0; i < khui_n_cust_menus; i++) {\r
+            if (khui_cust_menus[i] == NULL)\r
+                break;\r
+        }\r
+\r
+        if (i >= khui_n_cust_menus) {\r
+\r
+            if (khui_n_cust_menus + 1 >= khui_nc_cust_menus) {\r
+                khui_nc_cust_menus = UBOUNDSS(khui_n_cust_menus + 1,\r
+                                              CACT_NC_ALLOC, CACT_NC_ALLOC);\r
+                khui_cust_menus =\r
+                    PREALLOC(khui_cust_menus,\r
+                             sizeof(khui_cust_menus[0]) * khui_nc_cust_menus);\r
+            }\r
+\r
+            i = khui_n_cust_menus ++;\r
+        }\r
+\r
+        khui_cust_menus[i] = d;\r
+\r
+        LeaveCriticalSection(&cs_actions);\r
+    }\r
+\r
     return d;\r
 }\r
 \r
+KHMEXP void KHMAPI\r
+khui_set_main_window(HWND hwnd) {\r
+    khui_hwnd_main = hwnd;\r
+}\r
+\r
+KHMEXP void KHMAPI\r
+khui_action_trigger(khm_int32 action, khui_action_context * ctx) {\r
+    khui_action_context save;\r
+\r
+    if (!khui_hwnd_main)\r
+       return;\r
+\r
+    if (ctx) {\r
+       khui_context_get(&save);\r
+\r
+       khui_context_set_indirect(ctx);\r
+    }\r
+\r
+    SendMessage(khui_hwnd_main, WM_COMMAND,\r
+               MAKEWPARAM(action, 0), (LPARAM) 0);\r
+\r
+    if (ctx) {\r
+       khui_context_set_indirect(&save);\r
+    }\r
+}\r
+\r
 KHMEXP khui_menu_def * KHMAPI \r
 khui_menu_dup(khui_menu_def * src)\r
 {\r
@@ -235,16 +455,16 @@ khui_menu_dup(khui_menu_def * src)
 \r
     d = khui_menu_create(src->cmd);\r
 \r
-    if(src->n_items == -1)\r
+    if (!(src->state & KHUI_MENUSTATE_ALLOCD))\r
         n = khui_action_list_length(src->items);\r
     else\r
         n = src->n_items;\r
 \r
-    for(i=0; i<n; i++) {\r
-        if(src->items[i].flags & KHUI_ACTIONREF_PACTION) {\r
-            khui_menu_add_paction(d, src->items[i].p_action, src->items[i].flags);\r
+    for (i=0; i<n; i++) {\r
+        if (src->items[i].flags & KHUI_ACTIONREF_PACTION) {\r
+            khui_menu_insert_paction(d, -1, src->items[i].p_action, src->items[i].flags);\r
         } else {\r
-            khui_menu_add_action(d, src->items[i].action);\r
+            khui_menu_insert_action(d, -1, src->items[i].action, 0);\r
         }\r
     }\r
 \r
@@ -258,8 +478,22 @@ khui_menu_delete(khui_menu_def * d)
 \r
     /* non-allocated menus are assumed to have no pointers to other\r
        allocated blocks */\r
-    if(!(d->state & KHUI_MENUSTATE_ALLOCD))\r
+    if(!(d->state & KHUI_MENUSTATE_ALLOCD)) {\r
+        /* we shouldn't have tried to delete a constant menu */\r
+#ifdef DEBUG\r
+        assert(FALSE);\r
+#endif\r
         return;\r
+    }\r
+\r
+    EnterCriticalSection(&cs_actions);\r
+    for (i=0; i < khui_n_cust_menus; i++) {\r
+        if (khui_cust_menus[i] == d) {\r
+            khui_cust_menus[i] = NULL;\r
+            break;\r
+        }\r
+    }\r
+    LeaveCriticalSection(&cs_actions);\r
 \r
     for(i=0; i< (int) d->n_items; i++) {\r
         if(d->items[i].flags & KHUI_ACTIONREF_FREE_PACTION)\r
@@ -271,8 +505,12 @@ khui_menu_delete(khui_menu_def * d)
     PFREE(d);\r
 }\r
 \r
-static void khui_menu_assert_size(khui_menu_def * d, size_t n)\r
+static void\r
+menu_assert_size(khui_menu_def * d, size_t n)\r
 {\r
+\r
+    assert(d->state & KHUI_MENUSTATE_ALLOCD);\r
+\r
     if(n > (int) d->nc_items) {\r
         khui_action_ref * ni;\r
 \r
@@ -284,34 +522,153 @@ static void khui_menu_assert_size(khui_menu_def * d, size_t n)
     }\r
 }\r
 \r
-KHMEXP void KHMAPI khui_menu_add_action(khui_menu_def * d, int id)\r
+static void\r
+menu_const_to_allocd(khui_menu_def * d)\r
 {\r
-    khui_menu_assert_size(d, d->n_items + 1);\r
-    d->items[d->n_items].flags = 0;\r
-    d->items[d->n_items ++].action = id;\r
+    khui_action_ref * olist;\r
+    khui_action_ref * nlist;\r
+    khm_size n;\r
+\r
+    assert(!(d->state & KHUI_MENUSTATE_ALLOCD));\r
+\r
+    olist = d->items;\r
+    n = khui_action_list_length(d->items);\r
+\r
+    d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS);\r
+    nlist = PMALLOC(sizeof(d->items[0]) * d->nc_items);\r
+    memcpy(nlist, olist, sizeof(d->items[0]) * n);\r
+\r
+    d->items = nlist;\r
+    d->n_items = n;\r
+    d->state |= KHUI_MENUSTATE_ALLOCD;\r
 }\r
 \r
-KHMEXP void KHMAPI khui_menu_add_paction(khui_menu_def * d, khui_action * act, int flags)\r
+KHMEXP void KHMAPI\r
+khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 action, khm_int32 flags)\r
 {\r
-    khui_menu_assert_size(d, d->n_items + 1);\r
-    d->items[d->n_items].flags = flags | KHUI_ACTIONREF_PACTION;\r
-    d->items[d->n_items ++].p_action = act;\r
+    if (!(d->state & KHUI_MENUSTATE_ALLOCD))\r
+        menu_const_to_allocd(d);\r
+\r
+    assert(d->state & KHUI_MENUSTATE_ALLOCD);\r
+    assert(action == KHUI_MENU_SEP || action > 0);\r
+\r
+    if (idx < 0 || idx > d->n_items)\r
+        idx = d->n_items;\r
+\r
+    menu_assert_size(d, d->n_items + 1);\r
+\r
+    if (idx < d->n_items) {\r
+        memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));\r
+    }\r
+\r
+    d->items[idx].flags = flags;\r
+    d->items[idx].action = action;\r
+    if (action == KHUI_MENU_SEP)\r
+        d->items[idx].flags |= KHUI_ACTIONREF_SEP;\r
+\r
+    d->n_items++;\r
+}\r
+\r
+KHMEXP void KHMAPI\r
+khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * paction, int flags)\r
+{\r
+\r
+    if (paction == NULL)\r
+        return;\r
+\r
+    if (!(d->state & KHUI_MENUSTATE_ALLOCD))\r
+        menu_const_to_allocd(d);\r
+\r
+    assert(d->state & KHUI_MENUSTATE_ALLOCD);\r
+\r
+    if (idx < 0 || idx > d->n_items)\r
+        idx = d->n_items;\r
+\r
+    menu_assert_size(d, d->n_items + 1);\r
+\r
+    if (idx < d->n_items) {\r
+        memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0]));\r
+    }\r
+\r
+    d->items[idx].flags = flags | KHUI_ACTIONREF_PACTION;\r
+    d->items[idx].p_action = paction;\r
+\r
+    d->n_items++;\r
 }\r
 \r
-KHMEXP khui_menu_def * KHMAPI khui_find_menu(int id) {\r
+KHMEXP void KHMAPI\r
+khui_menu_remove_action(khui_menu_def * d, khm_size idx) {\r
+\r
+    assert(d->state & KHUI_MENUSTATE_ALLOCD);\r
+\r
+    if (idx < 0 || idx >= d->n_items)\r
+        return;\r
+\r
+    if (idx < d->n_items - 1) {\r
+        memmove(&d->items[idx], &d->items[idx + 1],\r
+                ((d->n_items - 1) - idx) * sizeof(d->items[0]));\r
+    }\r
+\r
+    d->n_items--;\r
+}\r
+\r
+KHMEXP khm_size KHMAPI\r
+khui_menu_get_size(khui_menu_def * d) {\r
+\r
+    if (d->state & KHUI_MENUSTATE_ALLOCD)\r
+        return d->n_items;\r
+    else\r
+        return khui_action_list_length(d->items);\r
+}\r
+\r
+KHMEXP khui_action_ref *\r
+khui_menu_get_action(khui_menu_def * d, khm_size idx) {\r
+\r
+    khm_size n;\r
+\r
+    if (d->state & KHUI_MENUSTATE_ALLOCD)\r
+        n = d->n_items;\r
+    else\r
+        n = khui_action_list_length(d->items);\r
+\r
+    if (idx < 0 || idx >= n)\r
+        return NULL;\r
+\r
+    return &d->items[idx];\r
+}\r
+\r
+KHMEXP khui_menu_def * KHMAPI\r
+khui_find_menu(khm_int32 id) {\r
     khui_menu_def * d;\r
     int i;\r
 \r
-    d = khui_all_menus;\r
-    for(i=0;i<khui_n_all_menus;i++) {\r
-        if(id == d[i].cmd)\r
-            return &d[i];\r
-    }\r
+    if (id < KHUI_USERACTION_BASE) {\r
+        d = khui_all_menus;\r
+        for(i=0;i<khui_n_all_menus;i++) {\r
+            if(id == d[i].cmd)\r
+                return &d[i];\r
+        }\r
 \r
-    return NULL;\r
+        return NULL;\r
+    } else {\r
+        d = NULL;\r
+\r
+        EnterCriticalSection(&cs_actions);\r
+        for (i=0; i < khui_n_cust_menus; i++) {\r
+            if (khui_cust_menus[i] &&\r
+                khui_cust_menus[i]->cmd == id) {\r
+                d = khui_cust_menus[i];\r
+                break;\r
+            }\r
+        }\r
+        LeaveCriticalSection(&cs_actions);\r
+\r
+        return d;\r
+    }\r
 }\r
 \r
-KHMEXP khui_action * KHMAPI khui_find_action(int id) {\r
+KHMEXP khui_action * KHMAPI\r
+khui_find_action(khm_int32 id) {\r
     khui_action * act;\r
     int i;\r
 \r
@@ -321,12 +678,28 @@ KHMEXP khui_action * KHMAPI khui_find_action(int id) {
             return &act[i];\r
     }\r
 \r
-    return NULL;\r
+    act = NULL;\r
+\r
+    EnterCriticalSection(&cs_actions);\r
+    if (id >= KHUI_USERACTION_BASE &&\r
+        (id - KHUI_USERACTION_BASE) < khui_n_cust_actions) {\r
+        act = khui_cust_actions[id - KHUI_USERACTION_BASE];\r
+#ifdef DEBUG\r
+        assert(!act || act->cmd == id);\r
+#endif\r
+        if (act && act->state & KHUI_ACTIONSTATE_DELETED)\r
+            act = NULL;\r
+    }\r
+    LeaveCriticalSection(&cs_actions);\r
+\r
+    return act;\r
 }\r
 \r
-KHMEXP khui_action * KHMAPI khui_find_named_action(wchar_t * name) {\r
+KHMEXP khui_action * KHMAPI\r
+khui_find_named_action(const wchar_t * name) {\r
     int i;\r
     khui_action * act;\r
+    khui_action ** pact;\r
 \r
     if(!name)\r
         return NULL;\r
@@ -339,25 +712,42 @@ KHMEXP khui_action * KHMAPI khui_find_named_action(wchar_t * name) {
             return &act[i];\r
     }\r
 \r
+    pact = khui_cust_actions;\r
+    for(i=0;i<khui_n_cust_actions;i++) {\r
+        if(!pact[i] || !pact[i]->name)\r
+            continue;\r
+\r
+        if(!wcscmp(pact[i]->name, name)) {\r
+            if (pact[i]->state & KHUI_ACTIONSTATE_DELETED)\r
+                return NULL;\r
+            else\r
+                return pact[i];\r
+        }\r
+    }\r
+\r
     return NULL;\r
 }\r
 \r
-KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref) {\r
+KHMEXP size_t KHMAPI\r
+khui_action_list_length(khui_action_ref * ref) {\r
     size_t c = 0;\r
-    while(ref && ref->action != KHUI_MENU_END) {\r
+    while(ref && ref->action != KHUI_MENU_END &&\r
+          !(ref->flags & KHUI_ACTIONREF_END)) {\r
         c++;\r
         ref++;\r
     }\r
     return c;\r
 }\r
 \r
-KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)\r
+KHMEXP void KHMAPI\r
+khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)\r
 {\r
     khui_action_ref * r;\r
     khui_action * act;\r
 \r
     r = d->items;\r
-    while(r && r->action != KHUI_MENU_END) {\r
+    while(r && r->action != KHUI_MENU_END &&\r
+          (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {\r
         if(r->flags & KHUI_ACTIONREF_PACTION) {\r
             act = r->p_action;\r
         } else {\r
@@ -376,7 +766,8 @@ KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 cmd)
     kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);\r
 }\r
 \r
-KHMEXP void KHMAPI khui_check_action(int cmd, khm_boolean check) {\r
+KHMEXP void KHMAPI\r
+khui_check_action(khm_int32 cmd, khm_boolean check) {\r
     khui_action * act;\r
 \r
     act = khui_find_action(cmd);\r
@@ -393,14 +784,16 @@ KHMEXP void KHMAPI khui_check_action(int cmd, khm_boolean check) {
     kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0);\r
 }\r
 \r
-KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable)\r
+KHMEXP void KHMAPI\r
+khui_enable_actions(khui_menu_def * d, khm_boolean enable)\r
 {\r
     khui_action_ref * r;\r
     int delta = FALSE;\r
     khui_action * act;\r
 \r
     r = d->items;\r
-    while(r && r->action != KHUI_MENU_END) {\r
+    while(r && r->action != KHUI_MENU_END &&\r
+          (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) {\r
         if(r->flags & KHUI_ACTIONREF_PACTION) {\r
             act = r->p_action;\r
         } else {\r
@@ -426,7 +819,8 @@ KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable)
     }\r
 }\r
 \r
-KHMEXP void KHMAPI khui_enable_action(int cmd, khm_boolean enable) {\r
+KHMEXP void KHMAPI\r
+khui_enable_action(khm_int32 cmd, khm_boolean enable) {\r
     khui_action * act;\r
 \r
     act = khui_find_action(cmd);\r
@@ -443,7 +837,8 @@ KHMEXP void KHMAPI khui_enable_action(int cmd, khm_boolean enable) {
     kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0);\r
 }\r
 \r
-KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void) {\r
+KHMEXP HACCEL KHMAPI\r
+khui_create_global_accel_table(void) {\r
     int i;\r
     ACCEL * accels;\r
     HACCEL ha;\r
@@ -463,9 +858,9 @@ KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void) {
 }\r
 \r
 KHMEXP khm_boolean KHMAPI \r
-khui_get_cmd_accel_string(int cmd, \r
+khui_get_cmd_accel_string(khm_int32 cmd, \r
                           wchar_t * buf, \r
-                          size_t bufsiz) {\r
+                          khm_size bufsiz) {\r
     int i;\r
     khui_accel_def * def;\r
 \r
@@ -517,10 +912,46 @@ khui_get_cmd_accel_string(int cmd,
             ap = L"Enter";\r
             break;\r
 \r
+        case VK_F1:\r
+            ap = L"F1";\r
+            break;\r
+\r
+        case VK_F2:\r
+            ap = L"F2";\r
+            break;\r
+\r
+        case VK_F3:\r
+            ap = L"F3";\r
+            break;\r
+\r
+        case VK_F4:\r
+            ap = L"F4";\r
+            break;\r
+\r
         case VK_F5:\r
             ap = L"F5";\r
             break;\r
 \r
+        case VK_F6:\r
+            ap = L"F6";\r
+            break;\r
+\r
+        case VK_F7:\r
+            ap = L"F7";\r
+            break;\r
+\r
+        case VK_F8:\r
+            ap = L"F8";\r
+            break;\r
+\r
+        case VK_F9:\r
+            ap = L"F9";\r
+            break;\r
+\r
+        case VK_F10:\r
+            ap = L"F10";\r
+            break;\r
+\r
         case VK_DELETE:\r
             ap = L"Del";\r
             break;\r
@@ -824,6 +1255,20 @@ khui_context_set_ex(khui_scope scope,
     LeaveCriticalSection(&cs_actions);\r
 }\r
 \r
+KHMEXP void KHMAPI\r
+khui_context_set_indirect(khui_action_context * ctx)\r
+{\r
+    EnterCriticalSection(&cs_actions);\r
+\r
+    khuiint_context_release(&khui_ctx);\r
+\r
+    khuiint_copy_context(&khui_ctx, ctx);\r
+\r
+    khui_context_refresh();\r
+\r
+    LeaveCriticalSection(&cs_actions);\r
+}\r
+\r
 KHMEXP void KHMAPI \r
 khui_context_refresh(void) {\r
     khm_int32 flags;\r
index 14600b0b6f60f96f4ae37d3d7e832305585ef292..0627a67e5a468be3b8be223d6b79534d0866f3db 100644 (file)
@@ -29,6 +29,8 @@ This file was autogenerated from src/ui/actiondef.cfg and src/ui/actions.csv.
 Do not modify directly.\r
 */\r
 \r
+#define NOEXPORT\r
+\r
 #include<khuidefs.h>\r
 #include<khhelp.h>\r
 #include"../ui/resource.h"\r
@@ -36,11 +38,11 @@ Do not modify directly.
 khui_action khui_actions [] = {\r
 EOS\r
 \r
-$record_prefix = "{";\r
+$record_prefix = "ACTION_FULL(";\r
 \r
 $record_sep = ",\n";\r
 \r
-$record_postfix = "}";\r
+$record_postfix = ")";\r
 \r
 $file_postfix = <<EOS;\r
 \r
index dd4949849585a44eaaf0a1a386a69f49e52a6487..608ca40a2717a24f506cd1219e7b6975b7938037 100644 (file)
@@ -6,6 +6,7 @@ KHUI_MENU_OPTIONS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_OPTIONS,0,IDH_MENU
 KHUI_MENU_HELP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_HELP,0,IDH_MENU_HELP,0\r
 KHUI_MENU_LAYOUT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_LAYOUT,0,0,0\r
 KHUI_MENU_TOOLBARS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_TOOLBARS,0,0,0\r
+KHUI_MENU_COLUMNS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_CHOOSE_COLS,0,IDH_ACTION_CHOOSE_COLS,0\r
 KHUI_ACTION_PROPERTIES,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_PROPERTIES,0,IDH_ACTION_PROPERTIES,0\r
 KHUI_ACTION_EXIT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_EXIT,0,IDH_ACTION_EXIT,0\r
 KHUI_ACTION_SET_DEF_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_SET_DEF_ID,0,IDH_ACTION_SET_DEF_ID,0\r
@@ -15,10 +16,10 @@ KHUI_ACTION_NEW_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_NEW,0,IDB_TK_NEW_DIS,IDB_TK
 KHUI_ACTION_RENEW_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_REFRESH,0,IDB_TK_REFRESH_DIS,IDB_TK_REFRESH_SM,IDB_TK_REFRESH_DIS_SM,IDS_ACTION_RENEW_CRED,0,0,0\r
 KHUI_ACTION_DESTROY_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_DELETE,0,IDB_TK_DELETE_DIS,IDB_TK_DELETE_SM,IDB_TK_DELETE_DIS_SM,IDS_ACTION_DESTROY_CRED,0,0,0\r
 KHUI_ACTION_LAYOUT_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_ID,0,0,KHUI_ACTIONSTATE_CHECKED\r
-KHUI_ACTION_LAYOUT_TYPE,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_TYPE,0,0,KHUI_ACTIONSTATE_DISABLED\r
+KHUI_ACTION_LAYOUT_TYPE,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_TYPE,0,0,0\r
 KHUI_ACTION_LAYOUT_LOC,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_LOC,0,0,0\r
+KHUI_ACTION_LAYOUT_CUST,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_CUST,0,0,0\r
 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\r
-KHUI_ACTION_CHOOSE_COLS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_CHOOSE_COLS,0,IDH_ACTION_CHOOSE_COLS,KHUI_ACTIONSTATE_DISABLED\r
 KHUI_ACTION_DEBUG_WINDOW,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_DEBUG_WINDOW,0,IDH_ACTION_DEBUG_WINDOW,KHUI_ACTIONSTATE_DISABLED\r
 KHUI_ACTION_VIEW_REFRESH,KHUI_ACTIONTYPE_TRIGGER,,IDB_VW_REFRESH,0,0,IDB_VW_REFRESH_SM,0,IDS_ACTION_VIEW_REFRESH,0,IDH_ACTION_VIEW_REFRESH,0\r
 KHUI_ACTION_OPT_IDENTS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_IDENTS,0,IDH_ACTION_OPT_INIT,0\r
@@ -37,3 +38,10 @@ KHUI_PACTION_CANCEL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_CANCEL,0,0,0
 KHUI_PACTION_CLOSE,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_CLOSE,0,0,0\r
 KHUI_PACTION_BLANK,0,,IDB_TB_SPACE,0,IDB_TB_SPACE,IDB_TB_BLANK_SM,IDB_TB_BLANK_SM,0,0,0,KHUI_ACTIONSTATE_DISABLED\r
 KHUI_PACTION_NEXT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NEXT,0,0,0\r
+KHUI_PACTION_YES,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_YES,0,0,0\r
+KHUI_PACTION_NO,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NO,0,0,0\r
+KHUI_PACTION_YESALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_YESALL,0,0,0\r
+KHUI_PACTION_NOALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NOALL,0,0,0\r
+KHUI_PACTION_KEEP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_KEEP,0,0,0\r
+KHUI_PACTION_REMOVE,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_REMOVE,0,0,0\r
+KHUI_PACTION_DISCARD,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_DISCARD,0,0,0\r
index dd096063b12135f3484f27e780b943fb1f9fb430..3d06a07e22b4cf85878226b0ce3e91c4a154771e 100644 (file)
@@ -207,11 +207,11 @@ khui_alert_set_message(khui_alert * alert, const wchar_t * message)
        (alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE)) {\r
 \r
         PFREE(alert->message);\r
-        alert->message = NULL;\r
         alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE;\r
-\r
     }\r
 \r
+    alert->message = NULL;\r
+\r
     if(message) {\r
         alert->message = PMALLOC(cb);\r
         StringCbCopy(alert->message, cb, message);\r
@@ -263,6 +263,20 @@ khui_alert_show(khui_alert * alert)
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
+KHMEXP khm_int32 KHMAPI\r
+khui_alert_show_modal(khui_alert * alert)\r
+{\r
+    khm_int32 rv;\r
+\r
+    assert(alert->magic == KHUI_ALERT_MAGIC);\r
+\r
+    khui_alert_hold(alert);\r
+    rv = kmq_send_message(KMSG_ALERT, KMSG_ALERT_SHOW_MODAL, 0,\r
+                          (void *) alert);\r
+\r
+    return rv;\r
+}\r
+\r
 KHMEXP khm_int32 KHMAPI\r
 khui_alert_queue(khui_alert * alert)\r
 {\r
index 51498c0b203134438bf3765187c787aa6fdfb121..ae8cd2f7c38a90b0106db00c8e89100166e29415 100644 (file)
@@ -182,12 +182,22 @@ khui_cfg_register(khui_config_node vparent,
         parent = cfgui_node_i_from_handle(vparent);\r
     }\r
 \r
-    //node->owner = kmm_this_plugin();\r
+    /* plugin handles should not be obtained lightly.  For the moment,\r
+       the cleanup of nodes doesn't happen until module unload and\r
+       module unload doesn't happen until all the plugin and module\r
+       handles have been freed. */\r
+    /* node->owner = kmm_this_plugin(); */\r
 \r
     EnterCriticalSection(&cs_cfgui);\r
     TADDCHILD(parent, node);\r
     LeaveCriticalSection(&cs_cfgui);\r
 \r
+    /* when the root config list changes, we need to notify the UI.\r
+       this way, the Options menu can be kept in sync. */\r
+    if (parent == cfgui_root_config) {\r
+        kmq_post_message(KMSG_ACT, KMSG_ACT_SYNC_CFG, 0, 0);\r
+    }\r
+\r
     return KHM_ERROR_SUCCESS;\r
 }\r
 \r
@@ -586,6 +596,11 @@ khui_cfg_set_param(khui_config_node vnode, LPARAM param) {
     LeaveCriticalSection(&cs_cfgui);\r
 }\r
 \r
+static void\r
+clear_node_data(khui_config_node_i * node) {\r
+    node->n_data = 0;\r
+}\r
+\r
 static cfg_node_data *\r
 get_node_data(khui_config_node_i * node,\r
               void * key, \r
@@ -623,6 +638,10 @@ get_node_data(khui_config_node_i * node,
     }\r
 \r
     node->data[node->n_data].key = key;\r
+    node->data[node->n_data].hwnd = NULL;\r
+    node->data[node->n_data].param = 0;\r
+    node->data[node->n_data].flags = 0;\r
+\r
     node->n_data++;\r
 \r
     return &(node->data[node->n_data - 1]);\r
@@ -763,6 +782,8 @@ cfgui_clear_params(khui_config_node_i * node) {
     node->hwnd = NULL;\r
     node->param = 0;\r
     node->flags &= KHUI_CNFLAGMASK_STATIC;\r
+    clear_node_data(node);\r
+\r
     c = TFIRSTCHILD(node);\r
     while(c) {\r
         cfgui_clear_params(c);\r
@@ -801,8 +822,7 @@ khui_cfg_set_flags(khui_config_node vnode,
     mask &= KHUI_CNFLAGMASK_DYNAMIC;\r
 \r
     EnterCriticalSection(&cs_cfgui);\r
-    if (cfgui_is_valid_node_handle(vnode) &&\r
-        hwnd_cfgui != NULL) {\r
+    if (cfgui_is_valid_node_handle(vnode)) {\r
 \r
         node = cfgui_node_i_from_handle(vnode);\r
 \r
@@ -926,8 +946,7 @@ khui_cfg_get_flags(khui_config_node vnode) {
         return 0;\r
 \r
     EnterCriticalSection(&cs_cfgui);\r
-    if (cfgui_is_valid_node_handle(vnode) &&\r
-        hwnd_cfgui != NULL) {\r
+    if (cfgui_is_valid_node_handle(vnode)) {\r
 \r
         node = cfgui_node_i_from_handle(vnode);\r
 \r
@@ -950,8 +969,7 @@ khui_cfg_get_name(khui_config_node vnode,
         return KHM_ERROR_INVALID_PARAM;\r
 \r
     EnterCriticalSection(&cs_cfgui);\r
-    if (cfgui_is_valid_node_handle(vnode) &&\r
-        hwnd_cfgui != NULL) {\r
+    if (cfgui_is_valid_node_handle(vnode)) {\r
         khm_size cb;\r
 \r
         node = cfgui_node_i_from_handle(vnode);\r
index dae98ff680cd8666f05a9fbdd14a78f4fda42b9f..082f9f25748effb2159b9c81d9437a34d5d9be82 100644 (file)
@@ -247,8 +247,7 @@ khui_cw_del_type(khui_new_creds * c,
 }\r
 \r
 KHMEXP khm_int32 KHMAPI \r
-khui_cw_find_type(\r
-                  khui_new_creds * c, \r
+khui_cw_find_type(khui_new_creds * c, \r
                   khm_int32 type, \r
                   khui_new_creds_by_type **t)\r
 {\r
@@ -271,8 +270,7 @@ khui_cw_find_type(
 \r
 \r
 KHMEXP khm_int32 KHMAPI \r
-khui_cw_enable_type(\r
-                    khui_new_creds * c,\r
+khui_cw_enable_type(khui_new_creds * c,\r
                     khm_int32 type,\r
                     khm_boolean enable)\r
 {\r
@@ -299,8 +297,7 @@ khui_cw_enable_type(
 }\r
 \r
 KHMEXP khm_boolean KHMAPI \r
-khui_cw_type_succeeded(\r
-                       khui_new_creds * c,\r
+khui_cw_type_succeeded(khui_new_creds * c,\r
                        khm_int32 type)\r
 {\r
     khui_new_creds_by_type * t;\r
@@ -543,8 +540,7 @@ khui_cw_get_prompt_count(khui_new_creds * c,
 }\r
 \r
 KHMEXP khm_int32 KHMAPI \r
-khui_cw_get_prompt(\r
-                   khui_new_creds * c, \r
+khui_cw_get_prompt(khui_new_creds * c, \r
                    khm_size idx, \r
                    khui_new_creds_prompt ** prompt)\r
 {\r
@@ -570,19 +566,29 @@ KHMEXP khm_int32 KHMAPI
 khui_cw_sync_prompt_values(khui_new_creds * c)\r
 {\r
     khm_size i;\r
+    khm_size n;\r
+    HWND hw;\r
+    wchar_t tmpbuf[KHUI_MAXCCH_PROMPT_VALUE];\r
 \r
     EnterCriticalSection(&c->cs);\r
-    for(i=0;i<c->n_prompts;i++) {\r
+ redo_loop:\r
+    n = c->n_prompts;\r
+    for(i=0; i<n; i++) {\r
         khui_new_creds_prompt * p;\r
+\r
         p = c->prompts[i];\r
         if(p->hwnd_edit) {\r
-            /* Ideally, we would retrieve the text to a temporary\r
-            buffer with the c->cs released, obtain c->cs and copy the\r
-            text to p->value.  However, I'm not going to bother as the\r
-            code paths we are touching here do not need c->cs while\r
-            setting p->value does */\r
-            GetWindowText(p->hwnd_edit, p->value, \r
-                          KHUI_MAXCCH_PROMPT_VALUE);\r
+            hw = p->hwnd_edit;\r
+            LeaveCriticalSection(&c->cs);\r
+\r
+            GetWindowText(hw, tmpbuf, ARRAYLENGTH(tmpbuf));\r
+\r
+            EnterCriticalSection(&c->cs);\r
+            if (n != c->n_prompts)\r
+                goto redo_loop;\r
+            SecureZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE);\r
+            StringCchCopy(p->value, KHUI_MAXCCH_PROMPT_VALUE,\r
+                          tmpbuf);\r
         }\r
     }\r
     LeaveCriticalSection(&c->cs);\r
index fccdab5492928b93ffde5ff9eed24fa52a841f70..e8f6cd64a7541300517b4bf431300c429b3be2e4 100644 (file)
 \r
 /*! \brief An action */\r
 typedef struct tag_khui_action {\r
-    int cmd;            /*!< command id */\r
-    int type;           /*!< combination of KHUI_ACTIONTYPE_* */\r
-    wchar_t * name;     /*!< name for named actions.  NULL if not named. */\r
-\r
-    /* normal, hot and disabled are toolbar sized bitmaps */\r
-    int ib_normal;      /*!< normal bitmap (index) */\r
-    int ib_hot;         /*!< hot bitmap (index) */\r
-    int ib_disabled;    /*!< disabled bitmap (index) */\r
-\r
-    int ib_icon;        /*!< index of small (16x16) icon (for menu) */\r
-    int ib_icon_dis;    /*!< index of disabled (greyed) icon */\r
-\r
-    int is_caption;     /*!< index of string resource for caption */\r
-    int is_tooltip;     /*!< same for description / tooltip */\r
-    int ih_topic;       /*!< help topic */\r
-    int state;          /*!< current state. combination of KHUI_ACTIONSTATE_* */\r
+    khm_int32 cmd;            /*!< action identifier */\r
+    khm_int32 type;           /*!< combination of KHUI_ACTIONTYPE_* */\r
+    wchar_t * name;           /*!< name for named actions.  NULL if\r
+                                not named. */\r
+\r
+    /* The following fields are only for use by NetIDMgr */\r
+    khm_int16 ib_normal;      /*!< (internal) normal bitmap (index) (toolbar sized icon) */\r
+    khm_int16 ib_hot;         /*!< (internal) hot bitmap (index) (toolbar sized icon) */\r
+    khm_int16 ib_disabled;    /*!< (internal) disabled bitmap (index) (toolbar sized icon) */\r
+\r
+    khm_int16 ib_icon;        /*!< (internal) index of small (16x16) icon (for menu) (small icon) */\r
+    khm_int16 ib_icon_dis;    /*!< (internal) index of disabled (greyed) icon (small icon) */\r
+\r
+    khm_int16 is_caption;     /*!< (internal) index of string resource for caption */\r
+    khm_int16 is_tooltip;     /*!< (internal) same for description / tooltip */\r
+    khm_int16 ih_topic;       /*!< (internal) help topic */\r
+\r
+    /* The following fields are specified for custom actions */\r
+    wchar_t * caption;        /*!< Caption (localized) (limited by\r
+                                  KHUI_MAXCCH_SHORT_DESC).  The\r
+                                  caption is used for representing the\r
+                                  action in menus and toolbars. */\r
+    wchar_t * tooltip;        /*!< Tooltip (localized) (limited by\r
+                                  KHUI_MAXCCH_SHORT_DESC).  If this is\r
+                                  specified, whenever the user hovers\r
+                                  over the menu item or toolbar button\r
+                                  representing the action, the tooltip\r
+                                  will be displayed either on a\r
+                                  tooltip window or in the status\r
+                                  bar. */\r
+    khm_handle listener;      /*!< Listener of this action.  Should be\r
+                                  a handle to a message\r
+                                  subscription. When the action is\r
+                                  invoked, a message of type\r
+                                  ::KMSG_ACT and subtype\r
+                                  ::KMSG_ACT_ACTIVATE will be posted\r
+                                  to this subscriber. The \a uparam\r
+                                  parameter of the message will have\r
+                                  the identifier of the action. */\r
+    void *    data;           /*!< User data for custom action.  This\r
+                                  field is not used by the UI library.\r
+                                  It is reserved for plugins to store\r
+                                  data that is specific for this\r
+                                  action.  The data that's passed in\r
+                                  in the \a userdata parameter to\r
+                                  khui_action_create() will be stored\r
+                                  here and can be retrieved by calling\r
+                                  khui_action_get_data(). */\r
+    void *    reserved1;      /*!< Reserved. */\r
+    void *    reserved2;      /*!< Reserved. */\r
+    void *    reserved3;      /*!< Reserved. */\r
+\r
+    /* For all actions */\r
+    int state;                /*!< current state. combination of\r
+                                  KHUI_ACTIONSTATE_* */\r
 } khui_action;\r
 \r
-/*! \brief Unknown action type */\r
+/*! \brief Unknown action type\r
+\r
+    Unknown action type.\r
+ */\r
 #define KHUI_ACTIONTYPE_NONE    0\r
 \r
-/*! \brief A trigger type action */\r
+/*! \brief A trigger type action\r
+\r
+    A trigger action usually triggers some event, which is what pretty\r
+    much every action does.\r
+*/\r
 #define KHUI_ACTIONTYPE_TRIGGER 1\r
 \r
 /*! \brief A toggle type action\r
@@ -65,12 +111,19 @@ typedef struct tag_khui_action {
  */\r
 #define KHUI_ACTIONTYPE_TOGGLE  2\r
 \r
-/*! \brief The action is enabled */\r
+/*! \brief The action is enabled\r
+\r
+    This is the default if no other state is specified.  Just means\r
+    not-disabled.\r
+*/\r
 #define KHUI_ACTIONSTATE_ENABLED    0\r
+\r
 /*! \brief The action is diabled */\r
 #define KHUI_ACTIONSTATE_DISABLED   1\r
+\r
 /*! \brief For toggle type actions, the action is checked */\r
 #define KHUI_ACTIONSTATE_CHECKED    2\r
+\r
 /*! \brief The action is hot\r
 \r
     Typically this means that the user is hovering the pointing device\r
@@ -78,31 +131,97 @@ typedef struct tag_khui_action {
  */\r
 #define KHUI_ACTIONSTATE_HOT        4\r
 \r
+/*! \brief The action has been marked for deletion\r
+\r
+    For custom actions, this means that the custom action was deleted.\r
+    The contents of the custom action fields are no longer valid.\r
+ */\r
+#define KHUI_ACTIONSTATE_DELETED    8\r
+\r
 #ifdef NOEXPORT\r
 #define ACTION_SIMPLE(c,cap,des,top) \\r
-    {c,KHUI_ACTIONTYPE_TRIGGER,0,0,0,0,0,cap,des,top,0}\r
+    {c,KHUI_ACTIONTYPE_TRIGGER,NULL,0,0,0,0,0,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}\r
 \r
-#define ACTION_FULL(cmd,type,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state) \\r
-    {cmd,type,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state}\r
+#define ACTION_FULL(cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state) \\r
+    {cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,NULL,NULL,NULL,NULL,NULL,NULL,NULL,state}\r
 \r
 #define ACTION_SIMPLE_IMAGE(c,inormal, ihot, idis, isml, ismld,cap, des, top) \\r
-    {c,KHUI_ACTIONTYPE_TRIGGER,inormal,ihot,idis,isml,ismld,cap,des,top,0}\r
+    {c,KHUI_ACTIONTYPE_TRIGGER,NULL,inormal,ihot,idis,isml,ismld,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0}\r
 #endif\r
 \r
-/*! \brief A reference to an action */\r
+/*! \brief A reference to an action\r
+\r
+    If the \a flags member has the KHUI_ACTIONREF_PACTION bit set,\r
+    then the action is referenced by the \a p_action member of the\r
+    union.  Otherwise the identifier for the action is specified by \a\r
+    action member.\r
+*/\r
 typedef struct tag_khui_action_ref {\r
-    int flags;\r
+    int flags;                  /*!< A combination of KHUI_ACTIONREF_* */\r
     union {\r
-        int action;\r
-        khui_action * p_action;\r
+        khm_int32     action;   /*!< The action identifier for the\r
+                                  action that is being referrred to.\r
+                                  Only valid if\r
+                                  ::KHUI_ACTIONREF_PACTION is not set\r
+                                  in \a flags. */\r
+        khui_action * p_action; /*!< A pointer to the ::khui_action\r
+                                  structure that describes the action\r
+                                  that is being referred to.  Only\r
+                                  valid if ::KHUI_ACTIONREF_PACTION is\r
+                                  set. */\r
     };\r
 } khui_action_ref;\r
 \r
+/*! \brief A submenu\r
+\r
+    There should exist a menu associated with the action that is being\r
+    referred.  When displaying this action in a menu, the contents of\r
+    the associated menu will appear as a submenu.\r
+ */\r
 #define KHUI_ACTIONREF_SUBMENU      0x01\r
+\r
+/*! \brief Separator\r
+\r
+    This is not an actual action, but represents a separator between\r
+    actions.  When displaying this action in a menu or a toolbar, a\r
+    separating line will be drawn in place of this action.  The \a\r
+    action and \a p_action members of the structures are unused if\r
+    this flag is set.\r
+ */\r
 #define KHUI_ACTIONREF_SEP          0x02\r
+\r
+/*! \brief Action by reference\r
+\r
+    The \a p_action member of the structure points to the\r
+    ::khui_action structure that describes the action.\r
+ */\r
 #define KHUI_ACTIONREF_PACTION      0x04\r
+\r
+#ifdef NOEXPORT\r
+/*! \brief Action should be freed\r
+\r
+    \note This flag is reserved for internal use in the NetIDMgr\r
+    application.  Do not use.\r
+ */\r
 #define KHUI_ACTIONREF_FREE_PACTION 0x08\r
+\r
+/*! \brief Marks the end of an action sequence\r
+\r
+    \note THis flag is reserved for internal use in the NetIDMgr\r
+    application. Do not use.\r
+ */\r
 #define KHUI_ACTIONREF_END          0x10\r
+#endif\r
+\r
+/*! \brief The default action\r
+\r
+    When this bit is set in an action reference that describes a menu,\r
+    the menu item will be the default item and will be rendered\r
+    differently from other menu items.  Only useful when defining\r
+    context menus.  In general, it is good practice to place the\r
+    default item at the top of a menu, although the UI library does\r
+    not enforce this.  This is purely meant as a rendering hint.\r
+ */\r
 #define KHUI_ACTIONREF_DEFAULT      0x20\r
 \r
 #ifdef NOEXPORT\r
@@ -113,35 +232,94 @@ typedef struct tag_khui_action_ref {
 #define MENU_END() {KHUI_ACTIONREF_END,KHUI_MENU_END}\r
 #endif\r
 \r
-/*! \brief Menu definition */\r
+/*! \brief Menu definition\r
+\r
+    Use the khui_menu_create(), khui_menu_insert_action(),\r
+    khui_menu_insert_paction(), khui_menu_get_size(),\r
+    khui_menu_get_action() functions to create and manipulate custom\r
+    menus.  Do not manipulate this structure directly as doing so may\r
+    cause inconsistencies in the UI library.\r
+*/\r
 typedef struct tag_khui_menu_def {\r
-    int cmd;                /*!< Action associated with menu */\r
-    int state;              /*!< combination of KHUI_MENUSTATE_* */\r
-    size_t n_items;         /*!< total number of items or -1 if not\r
-                             set.  If this is -1, then the list of\r
-                             actions must be terminated with a\r
-                             ACTION_LIST_END entry. */\r
-    size_t nc_items;        /*!< max number of items in the buffer\r
+    khm_int32 cmd;          /*!< Action associated with menu */\r
+    khm_int32 state;        /*!< combination of KHUI_MENUSTATE_* */\r
+    khm_size  n_items;      /*!< The number of actions in the \a items\r
+                              list.  If this is a custom menu, the\r
+                              ::KHUI_MENUSTATE_ALLOCD bit will be set,\r
+                              and the contents of this field will be\r
+                              valid.  Otherwise, the contents of this\r
+                              field is ignored and the list of actions\r
+                              must be terminated with a\r
+                              ACTION_LIST_END action. */\r
+    khm_size  nc_items;     /*!< max number of items in the buffer\r
                              alocated for items.  Ignored if\r
-                             KHUI_MENUSTATE_CONSTANT is set in \a\r
-                             state.*/\r
+                             ::KHUI_MENUSTATE_ALLOCD is not set in \a\r
+                             state. */\r
     khui_action_ref *items; /*!< Action list terminated by,\r
                              ACTION_LIST_END.  If \a n_items is set\r
                              to a value other than -1, the list\r
                              doesn't necessarily have to end with a\r
-                             ACTION_LIST_END. */\r
+                             ACTION_LIST_END.  When constructing a\r
+                             menu using khui_menu_* functions, they\r
+                             will set the size of this list in the \a\r
+                             n_items member, and there will be no\r
+                             ACTION_LIST_END action to terminate the\r
+                             list. */\r
 } khui_menu_def;\r
 \r
 #ifdef NOEXPORT\r
 #define CONSTMENU(c,s,i) {c,s,-1,-1,i}\r
 #endif\r
 \r
+/*! \brief Unspecified menu\r
+\r
+    Used when there is no single command associated with the entire\r
+    menu, such as for ad-hoc context menus.\r
+ */\r
+#define KHUI_MENU_NONE -3\r
+\r
+/*! \brief Menu end indicator\r
+\r
+    For static or constant menus this indicates that this action marks\r
+    the end of the list of actions which defined the menu.  This is\r
+    invalid if used in a dynamic menu (a menu with the\r
+    ::KHUI_MENUSTATE_ALLOCD bit set).\r
+ */\r
 #define KHUI_MENU_END -2\r
+\r
+/*! \brief Menu separator\r
+\r
+    A separator for actions.  When displaying a menu or showing a\r
+    toolbar based on a menu definition, a separator is rendered as a\r
+    bar separating the user interface elements for the actions on\r
+    either side of this.\r
+*/\r
 #define KHUI_MENU_SEP -1\r
 \r
+/*! \brief Constant menu\r
+\r
+    The contents of the menu cannot be modified (individual actions in\r
+    the menu may be modified, but the order and the contents of the\r
+    menu itself cannot be modified.\r
+\r
+    This is the default if ::KHUI_MENUSTATE_ALLOCD is not specified.\r
+ */\r
 #define KHUI_MENUSTATE_CONSTANT 0\r
+\r
+/*! \brief Variable menu\r
+\r
+    The menu is dnamically allocated.  The list of actions contained\r
+    in the menu can be modified.\r
+*/\r
 #define KHUI_MENUSTATE_ALLOCD   1\r
 \r
+#ifdef NOEXPORT\r
+/* predefined system menu */\r
+#define KHUI_MENUSTATE_SYSTEM   2\r
+#endif\r
+\r
+#ifdef NOEXPORT\r
+\r
 /*! \brief Accelerator definition */\r
 typedef struct tag_khui_accel_def {\r
     int cmd;\r
@@ -152,8 +330,6 @@ typedef struct tag_khui_accel_def {
 \r
 #define KHUI_ACCEL_SCOPE_GLOBAL 0\r
 \r
-#ifdef NOEXPORT\r
-\r
 extern khui_accel_def khui_accel_global[];\r
 extern int khui_n_accel_global;\r
 \r
@@ -167,11 +343,154 @@ extern int khui_n_all_menus;
 \r
 /* functions */\r
 \r
-KHMEXP khui_menu_def * KHMAPI khui_menu_create(int cmd);\r
-KHMEXP khui_menu_def * KHMAPI khui_menu_dup(khui_menu_def * src);\r
-KHMEXP void KHMAPI khui_menu_delete(khui_menu_def * d);\r
-KHMEXP void KHMAPI khui_menu_add_action(khui_menu_def * d, int id);\r
-KHMEXP void KHMAPI khui_menu_add_paction(khui_menu_def * d, khui_action * act, int flags);\r
+/*! \brief Create a new menu\r
+\r
+    Creates a new menu.  The returned data structure must be freed by\r
+    a call to khui_menu_delete().  Custom menus that are created this\r
+    way are not reference counted or maintained by the UI library.\r
+    The caller is responsible for calling khui_menu_delete() when the\r
+    data is no longer needed.\r
+\r
+    Specifiying an action in the \a action parameter will associate\r
+    the menu with the specified action.  In this case, if the action\r
+    is added to another menu with the ::KHUI_ACTIONREF_SUBMENU flag,\r
+    this menu will appear as a submenu within that menu.  Only one\r
+    menu can be associated with any given action.  Custom menus can\r
+    not be associated with standard actions.\r
+ */\r
+KHMEXP khui_menu_def * KHMAPI\r
+khui_menu_create(khm_int32 action);\r
+\r
+/*! \brief Duplicate a menu\r
+\r
+    Creates a copy of the specified menu.  The returned data structure\r
+    must be freed by a call to khui_menu_delete().  Custom menus are\r
+    not reference counted or maintained by the UI library.  The caller\r
+    is responsible for calling khui_menu_delete() when the data is no\r
+    longer needed.\r
+\r
+    Note that even if the original menu was associated with an action,\r
+    the duplicate will not be.  Modifying the duplicate will not\r
+    modify the original menu.  Only one menu can be associated with an\r
+    action.\r
+ */\r
+KHMEXP khui_menu_def * KHMAPI\r
+khui_menu_dup(khui_menu_def * src);\r
+\r
+/*! \brief Delete a menu\r
+\r
+    Deletes a menu created by a call to khui_menu_create() or\r
+    khui_menu_dup().  This frees up the memory and associated\r
+    resources used by the menu definition.  The pointer that is passed\r
+    in will no longer be valid.\r
+ */\r
+KHMEXP void KHMAPI\r
+khui_menu_delete(khui_menu_def * d);\r
+\r
+/*! \brief Insert an action into a menu\r
+\r
+    The action specified by \a cmd will be inserted in to the menu \a\r
+    d at index \a idx.\r
+\r
+    \param[in] d The menu to insert the action into\r
+\r
+    \param[in] idx The index at which to insert the action.  The index\r
+        is zero based.  If \a idx is (-1) or larger than the largest\r
+        index in the menu, the item is appended to the menu.\r
+\r
+    \param[in] cmd The command representing the action to insert into\r
+        the menu.  This should be either a standard action, a user\r
+        action created with khui_action_create(), or certain pseudo\r
+        actions.  Not all pseudo actions can be placed on a menu.\r
+\r
+    \param[in] flags Flags for the action.  This is a combination of\r
+        KHUI_ACTIONREF_* constants.  Currently, the only constants\r
+        that are valid for this function are: ::KHUI_ACTIONREF_SEP,\r
+        ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT.\r
+        ::KHUI_ACTIONREF_SEP will be automatically added if the\r
+        command is ::KHUI_MENU_SEP.\r
+\r
+    \note The ::khui_menu_def structure is not thread safe.  Multiple\r
+        threads modifying the same ::khui_menu_def structure may cause\r
+        thread safety issues.\r
+ */\r
+KHMEXP void KHMAPI\r
+khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 cmd, khm_int32 flags);\r
+\r
+#define khui_menu_add_action(d,c) khui_menu_insert_action((d),-1,(c),0)\r
+#pragma deprecated(khui_menu_add_action)\r
+\r
+#ifdef NOEXPORT\r
+\r
+/*! \brief Insert an action by reference into a menu\r
+\r
+    The action specified by \a act will be inserted into the menu \a d\r
+    at index \a idx.\r
+\r
+    \param[in] d The menu to inser the action into.\r
+\r
+    \param[in] idx The index at which to insert the action.  The index\r
+        is zero based.  If the index is (-1) or is larger than the\r
+        largest index in the menu, then the action is appended to the\r
+        menu.\r
+\r
+    \param[in] act The action to insert.  This is added by reference.\r
+        It is the callers reponsibility to ensure that the structure\r
+        pointed to by \a act is available throughout the lifetime of\r
+        the menu.\r
+\r
+    \param[in] flags Flags for the action.  This is a combination of\r
+        KHUI_ACTIONREF_* constants.  Currently, the only constants\r
+        that are valid for this function are: ::KHUI_ACTIONREF_SEP,\r
+        ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT.  For this\r
+        function, ::KHUI_ACTIONREF_PACTION will automatically be aded\r
+        when adding the action.  ::KHUI_ACTIONREF_SEP will be\r
+        automatically added if the command is ::KHUI_MENU_SEP.\r
+\r
+    \note The ::khui_menu_def structure is not thread safe.  Multiple\r
+        threads modifying the same ::khui_menu_def structure may cause\r
+        thread safety issues.\r
+*/\r
+KHMEXP void KHMAPI\r
+khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * act, khm_int32 flags);\r
+\r
+#define khui_menu_add_paction(d,a,f) khui_menu_insert_paction((d),-1,(a),(f))\r
+#pragma deprecated(khui_menu_add_paction)\r
+\r
+#endif\r
+\r
+/*! \brief Remove an action from a menu\r
+\r
+    The action at the specified index will be removed from the menu.\r
+  */\r
+KHMEXP void KHMAPI\r
+khui_menu_remove_action(khui_menu_def * d, khm_size idx);\r
+\r
+/*! \brief Get the number of items in the menu\r
+\r
+    Note that the count includes menu separators.  The indices of the\r
+    menu items range from 0 to one less than the value returned by\r
+    this function.\r
+ */\r
+KHMEXP khm_size KHMAPI\r
+khui_menu_get_size(khui_menu_def * d);\r
+\r
+/*! \brief Get the menu item at a specified index\r
+\r
+    The returned reference is only valid while the ::khui_menu_def\r
+    structure is valid.  In addition, the reference becomes invalid if\r
+    the list of actions in the menu data structure is modified in any\r
+    way.\r
+\r
+    If the specified index is out of bounds, then the function returns\r
+    NULL.\r
+\r
+    \note The ::khui_menu_def structure is not thread safe.  Multiple\r
+        threads modifying the same ::khui_menu_def structure may cause\r
+        thread safety issues.\r
+ */\r
+KHMEXP khui_action_ref *\r
+khui_menu_get_action(khui_menu_def * d, khm_size idx);\r
 \r
 /*! \brief Action scope identifiers \r
 \r
@@ -399,6 +718,16 @@ khui_context_set_ex(khui_scope scope,
                     void * vparam,\r
                     khm_size cb_vparam);\r
 \r
+/*! \brief Set the current UI context using an existing context\r
+\r
+    Copies the context specified in \a ctx into the active UI context.\r
+\r
+    \param[in] ctx A pointer to a ::khui_action_context structure that\r
+        specifies the new UI context.  Cannot be NULL.\r
+*/\r
+KHMEXP void KHMAPI\r
+khui_context_set_indirect(khui_action_context * ctx);\r
+\r
 /*! \brief Obtain the current UI context\r
 \r
     The parameter specified by \a ctx will receive the current UI\r
@@ -501,21 +830,125 @@ khui_context_cursor_filter(khm_handle cred,
 \r
     \return TRUE if the operation was successful. FALSE otherwise.\r
  */\r
-KHMEXP khm_boolean KHMAPI khui_get_cmd_accel_string(int cmd, wchar_t * buf, size_t bufsiz);\r
+KHMEXP khm_boolean KHMAPI khui_get_cmd_accel_string(khm_int32 cmd, wchar_t * buf, khm_size bufsiz);\r
 \r
+#ifdef NOEXPORT\r
+/*! \brief Initializes the global accelerator table\r
+ */\r
 KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void);\r
+#endif\r
 \r
-/*! \brief Find a menu by id */\r
-KHMEXP khui_menu_def * KHMAPI khui_find_menu(int id);\r
+/*! \brief Find a menu by id\r
 \r
-/*! \brief Find an action by id */\r
-KHMEXP khui_action * KHMAPI khui_find_action(int id);\r
+    Finds the menu that is associated with the specified action.\r
+ */\r
+KHMEXP khui_menu_def * KHMAPI khui_find_menu(khm_int32 action);\r
 \r
+#ifdef NOEXPORT\r
+\r
+/* internal */\r
+KHMEXP void KHMAPI\r
+khui_set_main_window(HWND hwnd);\r
+\r
+#endif\r
+\r
+/*! \brief Trigger an action\r
+\r
+    Triggers the specified action using the specified UI context.\r
+\r
+    This function does not return until the specified action has been\r
+    processed.  Many standard actions are asynchronous and they will\r
+    return before processing will complete.\r
+\r
+    Pseudo actions should not be triggered using khui_action_trigger()\r
+    as they only carry meaning when invoked from specific windows or\r
+    contexts.\r
+\r
+    \param[in] action Action.  Should be one of the standard actions\r
+        or an action created by khui_action_create()\r
+\r
+    \param[in] ctx The UI context to use for the action.  If this is\r
+        NULL, the action will be triggered under the current UI context.\r
+ */\r
+KHMEXP void KHMAPI\r
+khui_action_trigger(khm_int32 action, khui_action_context * ctx);\r
+\r
+/*! \brief Find an action by id\r
+\r
+    \note This function should not be used by plugins.  It is there\r
+        for use by the NetIDMgr application.\r
+*/\r
+KHMEXP khui_action * KHMAPI khui_find_action(khm_int32 action);\r
+\r
+#ifdef NOEXPORT\r
 /*! \brief Get the length of the action list */\r
 KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref);\r
+#endif\r
+\r
+/*! \brief Create a new action\r
+\r
+    \param[in] name Name for a named action.  The name must be unique\r
+        among all registered actions. (limited by KHUI_MAXCCH_NAME)\r
+        (Optional. Set to NULL if the action is not a named action.)\r
+\r
+    \param[in] caption The localized caption for the action.  This\r
+        will be shown in menus, toolbars and buttons when the action\r
+        needs to be represented. (limited by KHUI_MAXCCH_SHORT_DESC)\r
+        (Required)\r
+\r
+    \param[in] tooltip The localized tooltip for the action. (limited\r
+        by KHUI_MAXCCH_SHORT_DESC) (Optional, set to NULL if there is\r
+        no tooltip associated with the action)\r
+\r
+    \param[in] hsub The subscription that is notified when the action\r
+        is triggered. (Optional) The subscription can be created with\r
+        kmq_create_subscription().  The handle will be released when\r
+        it is no longer needed.  Hence, the caller should not release\r
+        it.\r
+\r
+    \param[in] type The type of the action.  Currently it should be\r
+        set to either ::KHUI_ACTIONTYPE_TRIGGER or\r
+        ::KHUI_ACTIONTYPE_TOGGLE.  For ::KHUI_ACTIONTYPE_TOGGLE, the\r
+        initial state will be unchecked.  Use khui_check_action()\r
+        function to change the checked state of the action.\r
+\r
+    \param[in] userdata A custom value.\r
+\r
+    \return The identifier of the new action or zero if the action\r
+        could not be created.\r
+\r
+    \note For named custom actions, the name of the action can not be\r
+        the same as the name of a configuration node.  See\r
+        khui_cfg_register_node().\r
+ */\r
+KHMEXP khm_int32 KHMAPI\r
+khui_action_create(const wchar_t * name,\r
+                   const wchar_t * caption,\r
+                   const wchar_t * tooltip,\r
+                   void * userdata,\r
+                   khm_int32 type,\r
+                   khm_handle hsub);\r
+\r
+/* \brief Delete a custom action\r
+\r
+   Deletes a custom action created by a call to khui_action_create().\r
+   Custom actions should only be deleted when unloading a plugin.\r
+ */\r
+KHMEXP void KHMAPI\r
+khui_action_delete(khm_int32 action);\r
+\r
+/*! \brief Get the user data associated with a custom action\r
+\r
+    This function returns the user data that was specified when the\r
+    custom action was created usng khui_action_create().  If the\r
+    custom action identifier is invalid or if the custom action does\r
+    not contain any user data, this function will return NULL.\r
+ */\r
+KHMEXP void * KHMAPI\r
+khui_action_get_data(khm_int32 action);\r
 \r
 /*! \brief Find an action by name */\r
-KHMEXP khui_action * KHMAPI khui_find_named_action(wchar_t * name);\r
+KHMEXP khui_action * KHMAPI khui_find_named_action(const wchar_t * name);\r
 \r
 /*! \brief Enables or disables a group of actions\r
 \r
@@ -527,24 +960,32 @@ KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable);
 \r
 /*! \brief Enables or disables an action\r
 \r
-    The action designated by the command \a cmd will either be enabled\r
+    The action designated by the command \a action will either be enabled\r
     or disabled depending on the \a enable parameter.  If \a enable is\r
     TRUE then the action is enabled.\r
  */\r
-KHMEXP void KHMAPI khui_enable_action(int cmd, khm_boolean enable);\r
+KHMEXP void KHMAPI khui_enable_action(khm_int32 action, khm_boolean enable);\r
 \r
 /*! \brief Check an action in an action group\r
 \r
-    Marks the action denoted by \a cmd as checked and resets the\r
+    Marks the action denoted by \a action as checked and resets the\r
     checked bit in all other actions.\r
 \r
     \param[in] d A menu definition.\r
-    \param[in] cmd A command identifier.  Setting this to -1 will\r
+\r
+    \param[in] action A command identifier.  Setting this to -1 will\r
         reset the checked bit in all the actions in the menu\r
         definition.\r
  */\r
-KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 cmd);\r
+KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 action);\r
+\r
+/*! \brief Check an action\r
 \r
+    For toggle typed actions, this sets or resets the check.\r
+ */\r
+KHMEXP void KHMAPI khui_check_action(khm_int32 cmd, khm_boolean check);\r
+\r
+#ifdef NOEXPORT\r
 /*!\cond INTERNAL */\r
 \r
 /*! \brief Initialize actions\r
@@ -560,6 +1001,7 @@ KHMEXP void KHMAPI khui_init_actions(void);
 KHMEXP void KHMAPI khui_exit_actions(void);\r
 \r
 /*! \endcond */\r
+#endif\r
 \r
 /*@}*/\r
 /*@}*/\r
index 3f1c4307380bb62879fd485913ad3bfb1cff3c66..a5d4799e835d9dac44a7e19c986479e551360102 100644 (file)
@@ -42,7 +42,6 @@
 #define KHUI_ACTION_SET_SRCH_ID (KHUI_ACTION_BASE + 4)\r
 #define KHUI_ACTION_PASSWD_ID   (KHUI_ACTION_BASE + 7)\r
 #define KHUI_ACTION_NEW_CRED    (KHUI_ACTION_BASE + 8)\r
-#define KHUI_ACTION_CHOOSE_COLS (KHUI_ACTION_BASE + 9)\r
 #define KHUI_ACTION_DEBUG_WINDOW    (KHUI_ACTION_BASE + 10)\r
 #define KHUI_ACTION_VIEW_REFRESH    (KHUI_ACTION_BASE + 11)\r
 #define KHUI_ACTION_LAYOUT_ID   (KHUI_ACTION_BASE + 12)\r
@@ -63,6 +62,7 @@
 #define KHUI_ACTION_CLOSE_APP   (KHUI_ACTION_BASE + 27)\r
 #define KHUI_ACTION_IMPORT      (KHUI_ACTION_BASE + 28)\r
 #define KHUI_ACTION_OPT_PLUGINS (KHUI_ACTION_BASE + 29)\r
+#define KHUI_ACTION_LAYOUT_CUST (KHUI_ACTION_BASE + 30)\r
 /*@}*/\r
 \r
 /*! \name Pseudo actions \r
@@ -92,6 +92,17 @@ context.
 #define KHUI_PACTION_BLANK  (KHUI_PACTION_BASE + 15)\r
 #define KHUI_PACTION_NEXT   (KHUI_PACTION_BASE + 16)\r
 #define KHUI_PACTION_SELALL (KHUI_PACTION_BASE + 17)\r
+#define KHUI_PACTION_YES    (KHUI_PACTION_BASE + 18)\r
+#define KHUI_PACTION_NO     (KHUI_PACTION_BASE + 19)\r
+#define KHUI_PACTION_YESALL (KHUI_PACTION_BASE + 20)\r
+#define KHUI_PACTION_NOALL  (KHUI_PACTION_BASE + 21)\r
+#define KHUI_PACTION_REMOVE (KHUI_PACTION_BASE + 22)\r
+#define KHUI_PACTION_KEEP   (KHUI_PACTION_BASE + 23)\r
+#define KHUI_PACTION_DISCARD (KHUI_PACTION_BASE + 24)\r
+#define KHUI_PACTION_PGDN   (KHUI_PACTION_BASE + 25)\r
+#define KHUI_PACTION_PGUP   (KHUI_PACTION_BASE + 26)\r
+#define KHUI_PACTION_PGUP_EXTEND (KHUI_PACTION_BASE + 27)\r
+#define KHUI_PACTION_PGDN_EXTEND (KHUI_PACTION_BASE + 28)\r
 /*@}*/\r
 \r
 /*! \name Menus\r
@@ -115,6 +126,9 @@ Stock menus.
 #define KHUI_MENU_TOK_CTX   (KHUI_MENU_BASE + 9)\r
 #define KHUI_MENU_ICO_CTX_MIN    (KHUI_MENU_BASE + 12)\r
 #define KHUI_MENU_ICO_CTX_NORMAL (KHUI_MENU_BASE + 13)\r
+#define KHUI_MENU_CWHEADER_CTX   (KHUI_MENU_BASE + 14)\r
+\r
+#define KHUI_MENU_COLUMNS   (KHUI_MENU_BASE + 15)\r
 \r
 #define KHUI_PMENU_TOK_SEL  (KHUI_MENU_BASE + 10)\r
 #define KHUI_PMENU_ID_SEL   (KHUI_MENU_BASE + 11)\r
@@ -129,8 +143,15 @@ Stock menus.
 #define KHUI_TOOLBAR_STANDARD   (KHUI_TOOLBAR_BASE + 0)\r
 /*@}*/\r
 \r
-/* base for user actions */\r
+/*! \brief Base for user actions\r
+\r
+    When creating new actions, the UI library will allocate command\r
+    identifiers starting with this one.\r
+*/\r
 #define KHUI_USERACTION_BASE    (KHUI_ACTION_BASE + 10000)\r
+\r
+/*! \brief Does this command represent a user action? */\r
+#define IS_USERACTION(cmd) ((cmd) >= KHUI_USERACTION_BASE)\r
 /*@}*/\r
 /*@}*/\r
 \r
index 36b13a3338155ca0f946996164eae7e6e93c5aea..f10ffa198bdf70a9daa5a8564ece43f4eda9d420 100644 (file)
@@ -179,6 +179,9 @@ enum khui_alert_flags {
     KHUI_ALERT_FLAG_REQUEST_BALLOON =0x08000000,\r
     /*!< The alert should be displayed in a balloon */\r
 \r
+    KHUI_ALERT_FLAG_MODAL           =0x10000000,\r
+    /*!< Modal alert.  Do not set direclty. */\r
+\r
     KHUI_ALERT_FLAGMASK_RDWR        =0x0C000010,\r
     /*!< Bit mask of flags that can be set by khui_alert_set_flags() */\r
 };\r
@@ -306,6 +309,19 @@ khui_alert_add_command(khui_alert * alert,
 KHMEXP khm_int32 KHMAPI \r
 khui_alert_show(khui_alert * alert);\r
 \r
+/*! \brief Display a modal alert\r
+\r
+    Similar to khui_alert_show(), but shows a modal alert dialog.  The\r
+    function does not return until the user has closed the alert.\r
+\r
+    This function always opens an alert window (never shows a\r
+    balloon).\r
+\r
+    \note Should only be called from the UI thread.\r
+ */\r
+KHMEXP khm_int32 KHMAPI\r
+khui_alert_show_modal(khui_alert * alert);\r
+\r
 /*! \brief Queue an alert\r
 \r
     Instead of displaying the alert immediately, the alert is queued\r
index ac9fc614c5256822a0e0dee32371fb4f1da80e03..f124b513f381a81aef428058d1dd1cfaf9e62d5c 100644 (file)
@@ -131,11 +131,17 @@ typedef struct tag_khui_config_node_reg {
 /*! \brief Node represents a panel that is replicated for all child nodes */\r
 #define KHUI_CNFLAG_PLURAL        0x0004\r
 \r
-#define KHUI_CNFLAG_MODIFIED      0x0010\r
-#define KHUI_CNFLAG_APPLIED       0x0020\r
+/*! \brief System node\r
 \r
-#define KHUI_CNFLAGMASK_STATIC    0x000f\r
-#define KHUI_CNFLAGMASK_DYNAMIC   0x00f0\r
+    \note For internal use by the NetIDMgr application.  Do not use.\r
+*/\r
+#define KHUI_CNFLAG_SYSTEM        0x0010\r
+\r
+#define KHUI_CNFLAG_MODIFIED      0x0100\r
+#define KHUI_CNFLAG_APPLIED       0x0200\r
+\r
+#define KHUI_CNFLAGMASK_STATIC    0x00ff\r
+#define KHUI_CNFLAGMASK_DYNAMIC   0x0f00\r
 \r
 /*! \brief Maximum length of the name in characters\r
 \r
@@ -250,6 +256,10 @@ typedef struct tag_khui_config_init_data {
         of reg were invalid\r
     \retval KHM_ERROR_DUPLICATE A node with the same name exists as a\r
         child of the specified parent node.\r
+\r
+    \note The name (not the short or long description) of the node can\r
+        not be the same as the name of a custom action.  See\r
+        khui_action_create().\r
  */\r
 KHMEXP khm_int32 KHMAPI\r
 khui_cfg_register(khui_config_node parent,\r
index 257434454388ad0a2cd85b33db0b1db6c90fba9f..45df19779fdbd28381368feb860cdda625002418 100644 (file)
@@ -263,7 +263,7 @@ typedef struct tag_khui_new_creds {
     khm_size    nc_types;       /*!< Internal use */\r
 \r
     khm_int32   result;     /*!< One of ::KHUI_NC_RESULT_CANCEL or\r
-                                ::KHUI_NC_RESULT_GET_CREDS indicating\r
+                                ::KHUI_NC_RESULT_PROCESS indicating\r
                                 the result of the dialog with the\r
                                 user */\r
 \r
@@ -296,7 +296,7 @@ typedef struct tag_khui_new_creds {
 \r
 /*!\name Result values for khui_new_creds_t::result\r
   @{*/\r
-#define KHUI_NC_RESULT_GET_CREDS    0\r
+#define KHUI_NC_RESULT_PROCESS    0\r
 #define KHUI_NC_RESULT_CANCEL       1\r
 /*@}*/\r
 \r
diff --git a/src/windows/identity/uilib/khversion.h b/src/windows/identity/uilib/khversion.h
new file mode 100644 (file)
index 0000000..d5dc36d
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+ * Copyright (c) 2005 Massachusetts Institute of Technology\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person\r
+ * obtaining a copy of this software and associated documentation\r
+ * files (the "Software"), to deal in the Software without\r
+ * restriction, including without limitation the rights to use, copy,\r
+ * modify, merge, publish, distribute, sublicense, and/or sell copies\r
+ * of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be\r
+ * included in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+#ifndef __KHIMAIRA_KHUIDEFS_H\r
+#define __KHIMAIRA_KHUIDEFS_H\r
+\r
+\r
+\r
+#endif\r
index 814e2880827fad65039b0d85d6910b64c1f226da..b0da7d15d668f439ed13837ea5361a093c99405e 100644 (file)
@@ -307,16 +307,19 @@ duration_edit_proc(HWND hwnd,
 \r
             p = GetParent(hwnd);\r
 \r
-            /* we are being activated.  show the panel */\r
+            /* we are being activated. */\r
             if(tc->hw_slider == NULL) {\r
                 create_edit_sliders(hwnd, p, tc);\r
                 initialize_tracker(p, tc);\r
             }\r
+\r
             khui_tracker_reposition(tc);\r
+\r
+#ifdef SHOW_PANEL_ON_FIRST_ACTIVATE\r
             ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);\r
+#endif\r
 \r
             tc->act_time = GetTickCount();\r
-            //SetActiveWindow(p);\r
         }\r
         break;\r
 \r
@@ -338,18 +341,17 @@ duration_edit_proc(HWND hwnd,
         break;\r
 \r
     case KHUI_WM_NC_NOTIFY:\r
-        if(HIWORD(wParam) == WMNC_DIALOG_SETUP)\r
-            {\r
-                HWND p;\r
-\r
-                p = GetParent(hwnd);\r
+        if(HIWORD(wParam) == WMNC_DIALOG_SETUP) {\r
+            HWND p;\r
 \r
-                if(tc->hw_slider == NULL) {\r
-                    create_edit_sliders(hwnd,p,tc);\r
-                }\r
+            p = GetParent(hwnd);\r
 \r
-                initialize_tracker(p, tc);\r
+            if(tc->hw_slider == NULL) {\r
+                create_edit_sliders(hwnd,p,tc);\r
             }\r
+\r
+            initialize_tracker(p, tc);\r
+        }\r
         return TRUE;\r
 \r
     case WM_LBUTTONUP:\r
@@ -357,7 +359,7 @@ duration_edit_proc(HWND hwnd,
             DWORD tm;\r
 \r
             tm = GetTickCount();\r
-            if (tm - tc->act_time > 500)\r
+            if (tm - tc->act_time > 000)\r
                 ShowWindow(tc->hw_slider, SW_HIDE);\r
         } else {\r
             ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE);\r
index 814920dce67b76703a7d034ae1a531228434df8b..6cf8ae44a0cbb313140295daf85d12c54c5966e5 100644 (file)
@@ -41,6 +41,9 @@ typedef struct tag_allocation {
     int    line;\r
     size_t size;\r
     void * ptr;\r
+#ifdef _WIN32\r
+    DWORD  thread;\r
+#endif\r
 \r
     LDCL(struct tag_allocation);\r
 } allocation;\r
@@ -165,6 +168,9 @@ perf_malloc(char * file, int line, size_t s) {
     a->line = line;\r
     a->size = s;\r
     a->ptr = ptr;\r
+#ifdef _WIN32\r
+    a->thread = GetCurrentThreadId();\r
+#endif\r
 \r
     h = HASHPTR(ptr);\r
 \r
@@ -246,11 +252,12 @@ perf_dump(char * file) {
         return;\r
 \r
     fprintf(f, "Leaked allocations list ....\n");\r
-    fprintf(f, "File\tLine\tSize\n");\r
+    fprintf(f, "File\tLine\tThread\tSize\n");\r
 \r
     for (i=0; i < HASHSIZE; i++) {\r
         for (a = ht[i]; a; a = LNEXT(a)) {\r
-            fprintf(f, "%s\t%6d\t%6d\n", a->file, a->line, a->size);\r
+            fprintf(f, "%s\t%6d\t%6d\t%6d\n", a->file, a->line,\r
+                   a->thread, a->size);\r
             total += a->size;\r
         }\r
     }\r