+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
!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
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
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
$(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
\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
#\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
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
\r
.SUFFIXES: .h\r
\r
-.SILENT:\r
-\r
!endif\r
-$(VERSIONINT): Makefile\r
+$(VERSIONINT): Makefile Makefile.w32\r
$(CP) << $(VERSIONINT)\r
/*\r
* This is an autogenerated file. Do not modify directly.\r
#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
-$(VERSIONEXT): Makefile\r
+$(VERSIONEXT): Makefile Makefile.w32\r
$(CP) << $(VERSIONEXT)\r
/* Copyright (c) 2004 Massachusetts Institute of Technology\r
*\r
#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
all: mkdirs $(CHMFILE) $(INCFILES)\r
\r
$(CHMFILE): netidmgr.hhp\r
- -hhc netidmgr.hhp\r
+ -$(HHC) netidmgr.hhp\r
$(CP) netidmgr.chm $(CHMFILE)\r
<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
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
--- /dev/null
+.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
\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
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
}\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
\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
}\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
\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
\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
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
}\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
\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
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
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
\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
*((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
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
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
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
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
rv = KHM_ERROR_SUCCESS;\r
}\r
\r
-_exit:\r
+ _exit:\r
kcdb_cred_unlock_write();\r
return rv;\r
}\r
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
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
}\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
}\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
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
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
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
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
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
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
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
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
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
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
}\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
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
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
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
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
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
\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
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
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
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
}\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
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
}\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
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
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
\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
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
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
#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
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
NULL,\r
NULL,\r
0) * sizeof(wchar_t);\r
- cbsize += sizeof(wchar_t);\r
}\r
\r
cbsize += GetTimeFormat(\r
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
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
khm_int32 filter,\r
kherr_serial serial) {\r
\r
+ khm_size idx;\r
+\r
assert(h);\r
\r
EnterCriticalSection(&cs_error);\r
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
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
\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
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
\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
\r
resolve_event_strings(e);\r
\r
-_exit:\r
+ _exit:\r
LeaveCriticalSection(&cs_error);\r
}\r
\r
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
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
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
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
/*!< 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
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
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
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
#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
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
#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
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
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
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
\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
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
#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
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
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
\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
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
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
if(csm)\r
khc_close_space(csm);\r
\r
+ _end_task();\r
+\r
return rv;\r
}\r
\r
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
\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
\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
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
/* $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
\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
\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
\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
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
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
\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
\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
/*! \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
}\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
}\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
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
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
\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
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
\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
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
\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
\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
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
} 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
exit_module = FALSE;\r
record_failure = FALSE;\r
\r
- ResetEvent(evt_exit);\r
-\r
_exit:\r
if(csp_mod) {\r
if(record_failure) {\r
/* 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
\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
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
}\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
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
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
#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
};\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
/* 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
ht_registrar = CreateThread(\r
NULL,\r
0,\r
- kmm_registrar,\r
+ kmmint_registrar,\r
NULL,\r
0,\r
&dummy);\r
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
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
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
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
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
\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
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
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
\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
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
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
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
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
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
-#\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)
\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
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
-#\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
\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
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
!= 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
\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
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
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
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
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
} 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
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
\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
}\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
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
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
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
\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
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
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
\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
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
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
\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
}\r
}\r
}\r
+\r
+ _end_task();\r
}\r
}\r
break;\r
&attr_id_krb5_flags))) {\r
rv = KHM_ERROR_UNKNOWN;\r
}\r
-\r
}\r
break;\r
\r
#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
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
#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
--- /dev/null
+; // ** 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
//{{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
#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
\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
{\r
VALUE "Translation", 0x409, 1200\r
}\r
-\r
}\r
-#\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
\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
}\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
}\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
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
#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
-/*\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, §ions);\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(®, 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, ®);\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(®, 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, ®);\r
-#endif\r
-\r
- ZeroMemory(®, 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, ®);\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(®, 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, ®);\r
-\r
- ZeroMemory(®, 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, ®);\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, §ions);
+
+ /* 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(®, 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, ®);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(®, 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, ®);
+
+ ZeroMemory(®, 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, ®);
+
+ khui_cfg_release(node);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(®, 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, ®);
+
+ ZeroMemory(®, 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, ®);
+
+ 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);
+}
\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
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
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
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
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
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
#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
FILETIME ft, eft;\r
khm_int32 ti;\r
\r
-\r
#ifdef KRB5_TC_NOTICKET\r
flags = KRB5_TC_NOTICKET;\r
#else\r
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
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
}\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
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
\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
\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
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
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
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
&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
&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
\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
\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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
#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
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
\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
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
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
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
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
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
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
}\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
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
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
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
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
&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
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
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
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
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
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
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
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
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
\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
&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
\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
\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
}\r
\r
k5_main_fiber = NULL;\r
-\r
}\r
\r
if(k5_sub != NULL) {\r
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
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
#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
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
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
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
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
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
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
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
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
//{{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
\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
-#\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)
+
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
\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
\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
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
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
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
!!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
\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
(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
== 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
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
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
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
\r
BOOL monitor;\r
BOOL renew;\r
+ BOOL halflife;\r
BOOL warn1;\r
BOOL warn2;\r
\r
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
\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
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
(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
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
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
== 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
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
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
#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
#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
\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
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
#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
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
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
{\r
LPNMHDR lpnm;\r
LPNMTREEVIEW lptv;\r
+ LPNMTVGETINFOTIP lpgi;\r
+ khui_config_node node;\r
\r
lpnm = (LPNMHDR) lParam;\r
\r
(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
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
}\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, ®);\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
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
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, ®);\r
\r
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, ®);\r
\r
- reg.flags = 0;\r
+ reg.flags = KHUI_CNFLAG_SYSTEM;\r
khui_cfg_release(node);\r
\r
reg.name = L"KhmNotifications";\r
#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
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
\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
\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
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
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
\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
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
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
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
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
\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
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
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
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
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
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
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
\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
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
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
{\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
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
\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
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
\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
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
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
}\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
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
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
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
\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
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
}\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
}\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
\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
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
\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
\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
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
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
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
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
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
\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
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
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
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
(select)?KCDB_CRED_FLAG_SELECTED:0,\r
KCDB_CRED_FLAG_SELECTED);\r
}\r
-\r
}\r
} else if (extend) {\r
int range_begin;\r
\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
(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
} 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
\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
\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
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
}\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
}\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
}\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
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
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
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
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
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
/* 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
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
\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
#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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
#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
#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
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
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
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
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
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
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
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
\r
#include<shlwapi.h>\r
#include<khmapp.h>\r
+#include<netidmgr_intver.h>\r
\r
#if DEBUG\r
#include<assert.h>\r
\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
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
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
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
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
}\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
\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
\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
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
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
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
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
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
} 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
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
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
\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
\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
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
SendMessage(hwtb,\r
TB_AUTOSIZE,\r
0,0);\r
-\r
+ \r
SendMessage(hwtb,\r
TB_GETMAXSIZE,\r
0,\r
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
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
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
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
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
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
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
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
}\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
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
} 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
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
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
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
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
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
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
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
\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
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
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
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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
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
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
\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
}\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(¬ifier_modal_loop);\r
+ }\r
+ }\r
+ break;\r
}\r
} else if (m->type == KMSG_CRED &&\r
m->subtype == KMSG_CRED_ROOTDELTA) {\r
}\r
}\r
/* fallthrough */\r
+ case NIN_BALLOONHIDE:\r
case NIN_BALLOONTIMEOUT:\r
khm_notify_icon_change(KHERR_NONE);\r
if (current_alert) {\r
}\r
break;\r
#endif\r
+\r
}\r
} else if (uMsg == WM_TIMER) {\r
if (wParam == KHUI_TRIGGER_TIMER_ID) {\r
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
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
\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
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
\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
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
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
//{{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
#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
\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
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(¤t);\r
+\r
+ /* wha?? */\r
+ if (CompareFileTime(issue, expire) >= 0)\r
+ return current;\r
+\r
+ lifetime = FtSub(expire, issue);\r
+ icurrent = FtToInt(¤t);\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
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
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
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
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
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
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
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
&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
\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
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
\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
\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
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
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
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
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
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
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
\r
Do not modify directly.\r
*/\r
+#define NOEXPORT\r
#include<khuidefs.h>\r
\r
khui_accel_def khui_accel_global[] = {\r
#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
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
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
};\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
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
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
\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
};\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
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
\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
\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
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
}\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
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
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
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
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
}\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
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
}\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
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
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
Do not modify directly.\r
*/\r
\r
+#define NOEXPORT\r
+\r
#include<khuidefs.h>\r
#include<khhelp.h>\r
#include"../ui/resource.h"\r
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
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
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
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
(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
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
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
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
}\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
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
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
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
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
}\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
\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
}\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
}\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
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
\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
*/\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
*/\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
#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
\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
\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
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
\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
\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
KHMEXP void KHMAPI khui_exit_actions(void);\r
\r
/*! \endcond */\r
+#endif\r
\r
/*@}*/\r
/*@}*/\r
#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
#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
#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
#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
#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
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
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
/*! \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
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
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
\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
--- /dev/null
+/*\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
\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
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
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
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
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
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