Version=2\r
AppVersion=0.1.1.0\r
Date=Nov 01, 2005\r
-# Alpha release of NetIDMgr\r
+# Beta 1 release of NetIDMgr\r
\r
#----------------------------------------------------------------\r
Version=3\r
AppVersion=0.1.2.0\r
-Date=NOTRELEASED\r
-# Beta release\r
+Date=Nov 30, 2005\r
+# Beta 2 release\r
\r
NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION)\r
NETIDMGR_COMMENT_STR_1033=Official build. Please send bug reports to kfw-bugs@MIT.EDU\r
!elseif "$(KH_RELEASE)" == "PRERELEASE"\r
-NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION) Alpha\r
+NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION) Prelease $(NETIDMGR_RELEASEDESC)\r
NETIDMGR_COMMENT_STR_1033=Prerelease build. Please send bug reports to kfw-bugs@MIT.EDU\r
!elseif "$(KH_RELEASE)" == "PRIVATE"\r
NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION).PRIVATE\r
# Version info\r
NETIDMGR_VERSION_MAJOR=0\r
NETIDMGR_VERSION_MINOR=1\r
-NETIDMGR_VERSION_PATCH=2\r
+NETIDMGR_VERSION_PATCH=3\r
NETIDMGR_VERSION_AUX=0\r
+NETIDMGR_RELEASEDESC=Beta 3\r
\r
# The API version. This number must be incremented each time the API\r
# changes. Plugins specify the version of the API that they were\r
khcwarn=$(khcwarn) /WX\r
!endif\r
\r
+#DEBUG_SYMBOLS\r
+ldebug=$(ldebug) /DEBUG\r
+cdebug=$(cdebug) -Os -Zi\r
+\r
khcflags=$(cdebug) $(cflags) $(incflags) $(khdefines) $(khcwarn)\r
khlguiflags=$(ldebug) $(guilflags)\r
khlconflags=$(ldebug) $(conlflags)\r
- <b>0.1.1</b> First Alpha release <em>Nov 01, 2005</em>\n\r
Released along with Kerberos for Windows 3.0.0 beta.\r
\r
- - <b>0.1.2</b> (tbd) <em>[tbd]</em>\n\r
+ - <b>0.1.2</b> Second Alpha release <em>Nov 30, 2005</em>\n\r
+ Released along with Kerberos for Windows 3.0.0 beta 2.\r
*/\r
-#define NIDM_HELPFILE L"netidmgr.chm"\r
-\r
#define IDH_WELCOME 1000\r
#define IDH_WIN_MAIN 1001\r
\r
LONG rv = ERROR_SUCCESS;\r
\r
hkp = hkey;\r
+ t = sSubKey;\r
+\r
+ /* check for case insensitive prefix first */\r
+ if (!wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {\r
+ HKEY hkt;\r
+\r
+ t = sSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);\r
+\r
+#ifdef DEBUG\r
+ assert(*t == L'\0' || *t == L'\\');\r
+#endif\r
+\r
+ rv = RegOpenKeyEx(hkp,\r
+ CONFIG_REGPATHW,\r
+ ulOptions,\r
+ samDesired,\r
+ &hkt);\r
+\r
+ if (rv != ERROR_SUCCESS)\r
+ return rv;\r
+\r
+ if (*t == L'\0') {\r
+ *phkResult = hkt;\r
+ return rv;\r
+ }\r
+\r
+ t++;\r
+ hkp = hkt;\r
+ }\r
\r
/* descend down the components of the subkey */\r
- t = sSubKey;\r
while(TRUE) {\r
wchar_t * slash;\r
HKEY hkt;\r
goto _cleanup;\r
}\r
\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if (!(wcsnicmp(sk_name, t, cch))) {\r
+ if (!(wcsncmp(sk_name, t, cch))) {\r
/* bingo! ?? */\r
if (cch < KCONF_MAXCCH_NAME &&\r
(sk_name[cch] == L'\0' ||\r
\r
LONG\r
khcint_RegCreateKeyEx(HKEY hKey,\r
- LPCTSTR lpSubKey,\r
+ LPCWSTR lpSubKey,\r
DWORD Reserved,\r
- LPTSTR lpClass,\r
+ LPWSTR lpClass,\r
DWORD dwOptions,\r
REGSAM samDesired,\r
LPSECURITY_ATTRIBUTES lpSecurityAttributes,\r
\r
hkp = hKey;\r
t = lpSubKey;\r
+\r
+ /* check for case insensitive prefix first */\r
+ if (!wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) {\r
+ HKEY hkt;\r
+\r
+ t = lpSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1);\r
+\r
+#ifdef DEBUG\r
+ assert(*t == L'\0' || *t == L'\\');\r
+#endif\r
+\r
+ rv = RegCreateKeyEx(hkp,\r
+ CONFIG_REGPATHW,\r
+ Reserved,\r
+ lpClass,\r
+ dwOptions,\r
+ samDesired,\r
+ lpSecurityAttributes,\r
+ &hkt,\r
+ lpdwDisposition);\r
+\r
+ if (rv != ERROR_SUCCESS)\r
+ return rv;\r
+\r
+ if (*t == L'\0') {\r
+ *phkResult = hkt;\r
+ return rv;\r
+ }\r
+\r
+ t++;\r
+ hkp = hkt;\r
+ }\r
+\r
while(TRUE) {\r
wchar_t * slash;\r
HKEY hkt;\r
if (hkp != hKey)\r
RegCloseKey(hkp);\r
hkp = hkt;\r
-\r
} else {\r
\r
rv = RegCreateKeyEx(hKey,\r
phkResult,\r
lpdwDisposition);\r
goto _cleanup;\r
-\r
}\r
}\r
\r
if (l != ERROR_SUCCESS)\r
break;\r
\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if (!(wcsnicmp(sk_name, t, cch))) {\r
+ if (!(wcsncmp(sk_name, t, cch))) {\r
/* bingo! ?? */\r
if (sk_name[cch] == L'\0' ||\r
sk_name[cch] == L'~') {\r
EnterCriticalSection(&cs_conf_global);\r
c = TFIRSTCHILD(p);\r
while(c) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(c->name && !wcsicmp(c->name, buf))\r
+ if(c->name && !wcscmp(c->name, buf))\r
break;\r
\r
c = LNEXT(c);\r
/* we are not creating the space, so it must exist in the form of a\r
registry key in HKLM or HKCU. If it existed as a schema, we\r
would have already retured it above. */\r
- if(flags & KCONF_FLAG_USER)\r
+ \r
+ if (flags & KCONF_FLAG_USER)\r
pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_USER);\r
\r
- if((!pkey || \r
- (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) != \r
- ERROR_SUCCESS)) \r
+ if((!pkey ||\r
+ (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=\r
+ ERROR_SUCCESS))\r
&& (flags & KCONF_FLAG_MACHINE)) {\r
\r
pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_MACHINE);\r
- if(!pkey || \r
- (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) != \r
+ if(!pkey ||\r
+ (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) !=\r
ERROR_SUCCESS)) {\r
*result = NULL;\r
+\r
return KHM_ERROR_NOT_FOUND;\r
}\r
}\r
\r
if(c->schema && khc_is_schema_handle(conf)) {\r
for(i=0;i<c->nSchema;i++) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(c->schema[i].type == KC_STRING && !wcsicmp(value, c->schema[i].name)) {\r
+ if(c->schema[i].type == KC_STRING && !wcscmp(value, c->schema[i].name)) {\r
/* found it */\r
size_t cbsize = 0;\r
\r
\r
if(c->schema && khc_is_schema_handle(conf)) {\r
for(i=0;i<c->nSchema;i++) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(c->schema[i].type == KC_INT32 && !wcsicmp(value, c->schema[i].name)) {\r
+ if(c->schema[i].type == KC_INT32 && !wcscmp(value, c->schema[i].name)) {\r
*buf = (khm_int32) c->schema[i].value;\r
rv = KHM_ERROR_SUCCESS;\r
goto _exit;\r
\r
if(c->schema && khc_is_schema_handle(conf)) {\r
for(i=0;i<c->nSchema;i++) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(c->schema[i].type == KC_INT64 && !wcsicmp(value, c->schema[i].name)) {\r
+ if(c->schema[i].type == KC_INT64 && !wcscmp(value, c->schema[i].name)) {\r
*buf = (khm_int64) c->schema[i].value;\r
rv = KHM_ERROR_SUCCESS;\r
goto _exit;\r
int i;\r
\r
for(i=0; i<c->nSchema; i++) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(!wcsicmp(c->schema[i].name, value)) {\r
+ if(!wcscmp(c->schema[i].name, value)) {\r
return c->schema[i].type;\r
}\r
}\r
\r
if(c->schema) {\r
for(i=0; i<c->nSchema; i++) {\r
- /* FIX ME - This is not what we intended to do. We want\r
- * a case sensitive match but we are running into a problem \r
- * because of "HKLM\SOFTWARE" and "HKCU\Software"\r
- */\r
- if(!wcsicmp(c->schema[i].name, value)) {\r
+ if(!wcscmp(c->schema[i].name, value)) {\r
rv |= KCONF_FLAG_SCHEMA;\r
break;\r
}\r
\r
if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) {\r
code = KHM_ERROR_INVALID_PARAM;\r
- goto _exit;\r
+ goto _exit_nolock;\r
}\r
\r
if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) {\r
code = KHM_ERROR_UNKNOWN;\r
- goto _exit;\r
+ goto _exit_nolock;\r
}\r
\r
kcdb_cred_lock_read();\r
\r
_exit:\r
kcdb_cred_unlock_read();\r
+_exit_nolock:\r
if(type)\r
kcdb_type_release_info(type);\r
if(attrib)\r
/* If the module is not in the pre-init state, we can't\r
initialize it. */\r
if(m->state != KMM_MODULE_STATE_PREINIT) {\r
- _report_mr1(KHERR_WARNING, MSG_IM_NOT_PREINIT, _int32(m->state));\r
+ _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state));\r
goto _exit;\r
}\r
\r
if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Flags", &i)) &&\r
(i & KMM_MODULE_FLAG_DISABLED)) {\r
\r
- _report_mr0(KHERR_ERROR, MSG_IM_DISABLED);\r
+ _report_mr0(KHERR_INFO, MSG_IM_DISABLED);\r
\r
m->state = KMM_MODULE_STATE_FAIL_DISABLED;\r
goto _exit;\r
\r
if(tm > 0 && \r
FtIntervalToSeconds((LPFILETIME) &ct) > fail_reset_time) {\r
-\r
i = 0;\r
khc_write_int32(csp_mod, L"FailureCount", 0);\r
khc_write_int64(csp_mod, L"FailureTime", 0);\r
-\r
}\r
\r
khc_read_int32(csp_mod, L"FailureReason", &last_reason);\r
if(i > max_fail_count && \r
last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) {\r
/* failed too many times */\r
- _report_mr0(KHERR_ERROR, MSG_IM_MAX_FAIL);\r
+ _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL);\r
\r
m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE;\r
goto _exit;\r
Plugins,KC_SPACE,0,Plugin Specific configuration\r
PluginMaxFailureCount,KC_INT32,3,Maximum number of failure counts before plugin is disabled\r
PluginFailureCountResetTime,KC_INT64,36000,Time after first failure at which the failure count is reset\r
- LoadList,KC_STRING,AfsCred,List of plugins that are active\r
_Schema,KC_SPACE,0,Plugin schema\r
Module,KC_STRING,<module name>,The name of the module that registered this plugin\r
Description,KC_STRING,<Description>,Description of the plugin\r
_Schema,KC_ENDSPACE,0,\r
Plugins,KC_ENDSPACE,0,\r
Modules,KC_SPACE,0,Module Specific configuration\r
- LoadList,KC_STRING,"OpenAFS,MITKrb5,MITKrb4",List of modules to load at startup\r
ModuleMaxFailureCount,KC_INT32,3,Maximum number of failure counts before module is disabled\r
ModuleFailureCountResetTime,KC_INT64,72000,Time after first failure at which the failure count is reset\r
_Schema,KC_SPACE,0,Module schema\r
FailureReason,KC_INT32,0,Reason for last failure. One of the module status values.\r
PluginList,KC_STRING,<plugins>,List of plugins implemented in the module\r
_Schema,KC_ENDSPACE,0,\r
- OpenAFS,KC_SPACE,0,OpenAFS Module\r
- ImagePath,KC_STRING,afscred.dll,\r
- PluginList,KC_STRING,AfsCred,\r
- OpenAFS,KC_ENDSPACE,0,\r
+# OpenAFS,KC_SPACE,0,OpenAFS Module\r
+# ImagePath,KC_STRING,afscred.dll,\r
+# PluginList,KC_STRING,AfsCred,\r
+# OpenAFS,KC_ENDSPACE,0,\r
MITKrb5,KC_SPACE,0,MIT Kerberos V\r
ImagePath,KC_STRING,krb5cred.dll,\r
PluginList,KC_STRING,Krb5Cred,\r
$(UIDIR)\actiondef.obj \\r
$(UIDIR)\acceldef.obj \\r
$(UIDIR)\configui.obj \\r
- $(UIDIR)\trackerwnd.obj\r
+ $(UIDIR)\trackerwnd.obj \\r
+ $(UIDIR)\version.obj\r
\r
RESFILES= \\r
$(OBJ)\nidmgrdll.res \\r
DECL_FUNC_PTR(krb5_get_prompt_types);\r
DECL_FUNC_PTR(krb5_build_principal_ext);\r
DECL_FUNC_PTR(krb5_cc_get_name);\r
+DECL_FUNC_PTR(krb5_cc_get_type);\r
DECL_FUNC_PTR(krb5_cc_resolve);\r
DECL_FUNC_PTR(krb5_cc_default);\r
DECL_FUNC_PTR(krb5_cc_default_name);\r
\r
FUNC_INFO k4_fi[] = {\r
MAKE_FUNC_INFO(get_krb_err_txt_entry),\r
- MAKE_FUNC_INFO(k_isinst),\r
- MAKE_FUNC_INFO(k_isname),\r
- MAKE_FUNC_INFO(k_isrealm),\r
- MAKE_FUNC_INFO(kadm_change_your_password),\r
- MAKE_FUNC_INFO(kname_parse),\r
- MAKE_FUNC_INFO(krb_get_cred),\r
- MAKE_FUNC_INFO(krb_get_krbhst),\r
- MAKE_FUNC_INFO(krb_get_lrealm),\r
- MAKE_FUNC_INFO(krb_get_pw_in_tkt),\r
- MAKE_FUNC_INFO(krb_get_tf_realm),\r
- MAKE_FUNC_INFO(krb_mk_req),\r
- MAKE_FUNC_INFO(krb_realmofhost),\r
- MAKE_FUNC_INFO(tf_init),\r
- MAKE_FUNC_INFO(tf_close),\r
- MAKE_FUNC_INFO(tf_get_cred),\r
- MAKE_FUNC_INFO(tf_get_pname),\r
- MAKE_FUNC_INFO(tf_get_pinst),\r
- MAKE_FUNC_INFO(LocalHostAddr),\r
- MAKE_FUNC_INFO(tkt_string),\r
- MAKE_FUNC_INFO(krb_set_tkt_string),\r
- MAKE_FUNC_INFO(initialize_krb_error_func),\r
- MAKE_FUNC_INFO(initialize_kadm_error_table),\r
- MAKE_FUNC_INFO(dest_tkt),\r
- /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX\r
- MAKE_FUNC_INFO(krb_in_tkt),\r
- MAKE_FUNC_INFO(krb_save_credentials),\r
- MAKE_FUNC_INFO(krb_get_krbconf2),\r
- MAKE_FUNC_INFO(krb_get_krbrealm2),\r
- MAKE_FUNC_INFO(krb_life_to_time),\r
- END_FUNC_INFO\r
+ MAKE_FUNC_INFO(k_isinst),\r
+ MAKE_FUNC_INFO(k_isname),\r
+ MAKE_FUNC_INFO(k_isrealm),\r
+ MAKE_FUNC_INFO(kadm_change_your_password),\r
+ MAKE_FUNC_INFO(kname_parse),\r
+ MAKE_FUNC_INFO(krb_get_cred),\r
+ MAKE_FUNC_INFO(krb_get_krbhst),\r
+ MAKE_FUNC_INFO(krb_get_lrealm),\r
+ MAKE_FUNC_INFO(krb_get_pw_in_tkt),\r
+ MAKE_FUNC_INFO(krb_get_tf_realm),\r
+ MAKE_FUNC_INFO(krb_mk_req),\r
+ MAKE_FUNC_INFO(krb_realmofhost),\r
+ MAKE_FUNC_INFO(tf_init),\r
+ MAKE_FUNC_INFO(tf_close),\r
+ MAKE_FUNC_INFO(tf_get_cred),\r
+ MAKE_FUNC_INFO(tf_get_pname),\r
+ MAKE_FUNC_INFO(tf_get_pinst),\r
+ MAKE_FUNC_INFO(LocalHostAddr),\r
+ MAKE_FUNC_INFO(tkt_string),\r
+ MAKE_FUNC_INFO(krb_set_tkt_string),\r
+ MAKE_FUNC_INFO(initialize_krb_error_func),\r
+ MAKE_FUNC_INFO(initialize_kadm_error_table),\r
+ MAKE_FUNC_INFO(dest_tkt),\r
+ /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX\r
+ MAKE_FUNC_INFO(krb_in_tkt),\r
+ MAKE_FUNC_INFO(krb_save_credentials),\r
+ MAKE_FUNC_INFO(krb_get_krbconf2),\r
+ MAKE_FUNC_INFO(krb_get_krbrealm2),\r
+ MAKE_FUNC_INFO(krb_life_to_time),\r
+ END_FUNC_INFO\r
};\r
\r
FUNC_INFO k5_fi[] = {\r
MAKE_FUNC_INFO(krb5_get_prompt_types),\r
MAKE_FUNC_INFO(krb5_build_principal_ext),\r
MAKE_FUNC_INFO(krb5_cc_get_name),\r
+ MAKE_FUNC_INFO(krb5_cc_get_type),\r
MAKE_FUNC_INFO(krb5_cc_resolve),\r
MAKE_FUNC_INFO(krb5_cc_default),\r
MAKE_FUNC_INFO(krb5_cc_default_name),\r
\r
FUNC_INFO k524_fi[] = {\r
MAKE_FUNC_INFO(krb524_init_ets),\r
- MAKE_FUNC_INFO(krb524_convert_creds_kdc),\r
- END_FUNC_INFO\r
+ MAKE_FUNC_INFO(krb524_convert_creds_kdc),\r
+ END_FUNC_INFO\r
};\r
\r
FUNC_INFO profile_fi[] = {\r
\r
FUNC_INFO ce_fi[] = {\r
MAKE_FUNC_INFO(com_err),\r
- MAKE_FUNC_INFO(error_message),\r
- END_FUNC_INFO\r
+ MAKE_FUNC_INFO(error_message),\r
+ END_FUNC_INFO\r
};\r
\r
FUNC_INFO service_fi[] = {\r
\r
FUNC_INFO lsa_fi[] = {\r
MAKE_FUNC_INFO(LsaConnectUntrusted),\r
- MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),\r
- MAKE_FUNC_INFO(LsaCallAuthenticationPackage),\r
- MAKE_FUNC_INFO(LsaFreeReturnBuffer),\r
- MAKE_FUNC_INFO(LsaGetLogonSessionData),\r
- END_FUNC_INFO\r
+ MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),\r
+ MAKE_FUNC_INFO(LsaCallAuthenticationPackage),\r
+ MAKE_FUNC_INFO(LsaFreeReturnBuffer),\r
+ MAKE_FUNC_INFO(LsaGetLogonSessionData),\r
+ END_FUNC_INFO\r
};\r
\r
// psapi functions\r
extern DECL_FUNC_PTR(krb5_get_prompt_types);\r
extern DECL_FUNC_PTR(krb5_build_principal_ext);\r
extern DECL_FUNC_PTR(krb5_cc_get_name);\r
+extern DECL_FUNC_PTR(krb5_cc_get_type);\r
extern DECL_FUNC_PTR(krb5_cc_resolve);\r
extern DECL_FUNC_PTR(krb5_cc_default);\r
extern DECL_FUNC_PTR(krb5_cc_default_name);\r
} while(FALSE);\r
}\r
\r
+#ifndef FAILOVER_TO_DEFAULT_CCACHE\r
+ rc = 1;\r
+#endif\r
if (*cache == 0\r
#ifdef FAILOVER_TO_DEFAULT_CCACHE\r
&& (rc = (*pkrb5_cc_default)(*ctx, cache))\r
\r
/* $Id$ */\r
\r
+#if _WIN32_WINNT < 0x501\r
+#undef _WIN32_WINNT\r
+#define _WIN32_WINNT 0x501\r
+#endif\r
+\r
#include<krbcred.h>\r
#include<krb5.h>\r
#include<assert.h>\r
/* not there. we need to add. but check a few things\r
first */\r
if (!PathFileExists(path)) {\r
- EDITBALLOONTIP bt;\r
wchar_t title[64];\r
wchar_t text[128];\r
\r
- bt.cbStruct = sizeof(bt);\r
- bt.pszTitle = title;\r
LoadString(hResModule, IDS_CFG_FCN_WARNING,\r
title, ARRAYLENGTH(title));\r
- bt.pszText = text;\r
+\r
LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND,\r
text, ARRAYLENGTH(text));\r
- bt.ttiIcon = TTI_WARNING;\r
-\r
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,\r
- EM_SHOWBALLOONTIP,\r
- 0,\r
- (LPARAM) &bt);\r
-\r
+#if _WIN32_WINNT >= 0x501\r
+ if (IS_COMMCTL6())\r
+ {\r
+ EDITBALLOONTIP bt;\r
+\r
+ bt.cbStruct = sizeof(bt);\r
+ bt.pszTitle = title;\r
+ bt.pszText = text;\r
+ bt.ttiIcon = TTI_WARNING;\r
+\r
+ SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,\r
+ EM_SHOWBALLOONTIP,\r
+ 0,\r
+ (LPARAM) &bt);\r
+ } else {\r
+#endif\r
+ MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);\r
+#if _WIN32_WINNT >= 0x501\r
+ }\r
+#endif\r
} else if (PathIsRelative(path)) {\r
- EDITBALLOONTIP bt;\r
wchar_t title[64];\r
wchar_t text[128];\r
\r
- bt.cbStruct = sizeof(bt);\r
- bt.pszTitle = title;\r
LoadString(hResModule, IDS_CFG_FCN_WARNING,\r
title, ARRAYLENGTH(title));\r
- bt.pszText = text;\r
LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE,\r
text, ARRAYLENGTH(text));\r
- bt.ttiIcon = TTI_WARNING;\r
\r
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,\r
- EM_SHOWBALLOONTIP,\r
- 0,\r
- (LPARAM) &bt);\r
+#if _WIN32_WINNT >= 0x501\r
+ if (IS_COMMCTL6())\r
+ {\r
+ EDITBALLOONTIP bt;\r
+\r
+ bt.cbStruct = sizeof(bt);\r
+ bt.pszTitle = title;\r
+ bt.pszText = text;\r
+ bt.ttiIcon = TTI_WARNING;\r
+\r
+ SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,\r
+ EM_SHOWBALLOONTIP,\r
+ 0,\r
+ (LPARAM) &bt);\r
+ } else {\r
+#endif\r
+ MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);\r
+#if _WIN32_WINNT >= 0x501\r
+ }\r
+#endif\r
}\r
\r
k5_add_file_cc(&d->work, path);\r
static long get_tickets_from_cache(krb5_context ctx, \r
krb5_ccache cache)\r
{\r
- krb5_error_code code;\r
- krb5_principal KRBv5Principal;\r
- krb5_flags flags = 0;\r
- krb5_cc_cursor KRBv5Cursor;\r
- krb5_creds KRBv5Credentials;\r
+ krb5_error_code code;\r
+ krb5_principal KRBv5Principal;\r
+ krb5_flags flags = 0;\r
+ krb5_cc_cursor KRBv5Cursor;\r
+ krb5_creds KRBv5Credentials;\r
krb5_ticket *tkt=NULL;\r
- char *ClientName;\r
- char *PrincipalName;\r
- wchar_t wbuf[256]; /* temporary conversion buffer */\r
- wchar_t *wcc_name = NULL; /* credential cache name */\r
- char *sServerName;\r
+ char *ClientName;\r
+ char *PrincipalName;\r
+ wchar_t wbuf[256]; /* temporary conversion buffer */\r
+ wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */\r
+ char *sServerName;\r
khm_handle ident = NULL;\r
khm_handle cred = NULL;\r
time_t tt;\r
#endif\r
\r
{\r
- char * cc_name;\r
- size_t namelen;\r
+ const char * cc_name;\r
+ const char * cc_type;\r
\r
cc_name = (*pkrb5_cc_get_name)(ctx, cache);\r
if(cc_name) {\r
- namelen = strlen(cc_name);\r
- namelen = (namelen + 1 + 5) * sizeof(wchar_t);\r
- /* the +5 is for the possible addtion of API: or FILE:\r
- during the cannonicalization process */\r
- wcc_name = PMALLOC(namelen);\r
- AnsiStrToUnicode(wcc_name, namelen, cc_name);\r
- khm_krb5_canon_cc_name(wcc_name, namelen);\r
+ cc_type = (*pkrb5_cc_get_type)(ctx, cache);\r
+ if (cc_type) {\r
+ StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name);\r
+ } else {\r
+ AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name);\r
+ khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name));\r
+ }\r
+ } else {\r
+ cc_type = (*pkrb5_cc_get_type)(ctx, cache);\r
+ if (cc_type) {\r
+ StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type);\r
+ } else {\r
+#ifdef DEBUG\r
+ assert(FALSE);\r
+#endif\r
+ StringCbCopy(wcc_name, sizeof(wcc_name), L"");\r
+ }\r
}\r
}\r
\r
}\r
\r
_exit:\r
- if(wcc_name)\r
- PFREE(wcc_name);\r
\r
return code;\r
}\r
char *princ_name = NULL;\r
BOOL rc = FALSE;\r
\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds);\r
+#endif\r
if ( !pkrb5_init_context )\r
goto cleanup;\r
\r
if (code = pkrb5_init_context(&kcontext))\r
goto cleanup;\r
\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Resolving MSLSA\n");\r
+#endif\r
if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))\r
goto cleanup;\r
\r
if ( save_creds ) {\r
- if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Getting principal\n");\r
+#endif\r
+ if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))\r
goto cleanup;\r
\r
- if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Unparsing name\n");\r
+#endif\r
+ if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))\r
goto cleanup;\r
\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Unparsed [%S]. Resolving target cache\n", princ_name);\r
+#endif\r
/* TODO: actually look up the preferred ccache name */\r
- if ((code = pkrb5_cc_resolve(kcontext, princ_name, &ccache)) ||\r
- (code = pkrb5_cc_default(kcontext, &ccache)))\r
- goto cleanup;\r
+ if (code = pkrb5_cc_resolve(kcontext, princ_name, &ccache)) {\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", princ_name, code);\r
+#endif\r
+\r
+ if (code = pkrb5_cc_default(kcontext, &ccache)) {\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Failed to resolve default ccache. Code=%d", code);\r
+#endif\r
+ goto cleanup;\r
+ }\r
+ }\r
\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Initializing ccache\n");\r
+#endif\r
if (code = pkrb5_cc_initialize(kcontext, ccache, princ))\r
goto cleanup;\r
\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L"Copying credentials\n");\r
+#endif\r
if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))\r
goto cleanup;\r
\r
if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) \r
goto cleanup;\r
\r
- while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) \r
- {\r
+ while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, \r
+ &cursor, &creds))) {\r
if ( creds.ticket_flags & TKT_FLG_INITIAL ) {\r
rc = TRUE;\r
pkrb5_free_cred_contents(kcontext, &creds);\r
}\r
\r
cleanup:\r
+#ifdef DEBUG\r
+ kherr_debug_printf(L" Received code=%d", code);\r
+#endif\r
+\r
if (princ_name)\r
pkrb5_free_unparsed_name(kcontext, princ_name);\r
if (princ)\r
NULL,\r
&cb_ms);\r
\r
- if (rv != KHM_ERROR_TOO_LONG)\r
+ if (rv != KHM_ERROR_TOO_LONG || cb_ms <= sizeof(wchar_t) * 2)\r
goto _add_lru_realms;\r
\r
ms = PMALLOC(cb_ms);\r
\r
BOOL is_k5_identpro = TRUE;\r
\r
+khm_ui_4 k5_commctl_version;\r
+\r
kmm_module_locale locales[] = {\r
LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb5cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)\r
};\r
} else\r
goto _exit;\r
\r
+ k5_commctl_version = khm_get_commctl_version(NULL);\r
+\r
/* register the plugin */\r
ZeroMemory(&pi, sizeof(pi));\r
pi.name = KRB5_PLUGIN_NAME;\r
\r
khm_krb5_list_tickets(&ctx);\r
\r
+ /* If there is no default identity, then make this the default */\r
+ kcdb_identity_refresh(nc->identities[0]);\r
+ {\r
+ khm_handle tdefault = NULL;\r
+\r
+ if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {\r
+ kcdb_identity_release(tdefault);\r
+ } else {\r
+ kcdb_identity_set_default(nc->identities[0]);\r
+ }\r
+ }\r
+\r
/* also add the principal and the realm in to the\r
LRU lists */\r
rv = kcdb_identity_get_name(nc->identities[0],\r
assert(KHM_SUCCEEDED(rv));\r
\r
if (multi_string_find(wbuf,\r
- idname,\r
- KHM_CASE_SENSITIVE) \r
- != NULL)\r
- /* it's already there */\r
- goto _add_realm_to_LRU;\r
+ idname,\r
+ KHM_CASE_SENSITIVE) \r
+ != NULL) {\r
+ /* it's already there. We remove it here\r
+ and add it at the top of the LRU\r
+ list. */\r
+ multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);\r
+ }\r
} else {\r
multi_string_init(wbuf, cb_ms);\r
}\r
L"LRUPrincipals",\r
wbuf);\r
\r
- _add_realm_to_LRU:\r
-\r
atsign = wcschr(idname, L'@');\r
- assert(atsign != NULL);\r
+ if (atsign != NULL)\r
+ goto _done_with_LRU;\r
\r
atsign++;\r
- assert(*atsign != L'\0');\r
+\r
+ if (*atsign == L'\0')\r
+ goto _done_with_LRU;\r
\r
cb = cb_ms;\r
rv = khc_read_multi_string(csp_params,\r
assert(KHM_SUCCEEDED(rv));\r
} else if (rv == KHM_ERROR_SUCCESS) {\r
if (multi_string_find(wbuf,\r
- atsign,\r
- KHM_CASE_SENSITIVE)\r
- != NULL)\r
- goto _done_with_LRU;\r
+ atsign,\r
+ KHM_CASE_SENSITIVE)\r
+ != NULL) {\r
+ /* remove the realm and add it at the top\r
+ later. */\r
+ multi_string_delete(wbuf, atsign, KHM_CASE_SENSITIVE); \r
+ }\r
} else {\r
multi_string_init(wbuf, cb_ms);\r
}\r
\r
cb = cb_ms;\r
rv = multi_string_prepend(wbuf,\r
- &cb,\r
- atsign);\r
+ &cb,\r
+ atsign);\r
\r
if (rv == KHM_ERROR_TOO_LONG) {\r
- wbuf = realloc(wbuf, cb);\r
+ wbuf = PREALLOC(wbuf, cb);\r
\r
rv = multi_string_prepend(wbuf,\r
- &cb,\r
- atsign);\r
+ &cb,\r
+ atsign);\r
\r
assert(KHM_SUCCEEDED(rv));\r
}\r
\r
case KMSG_CRED_IMPORT:\r
{\r
- khm_krb5_ms2mit(TRUE);\r
+ khm_int32 t = 0;\r
+\r
+#ifdef DEBUG\r
+ assert(csp_params);\r
+#endif\r
+ khc_read_int32(csp_params, L"MsLsaImport", &t);\r
+\r
+ if (t == 1)\r
+ khm_krb5_ms2mit(TRUE);\r
}\r
break;\r
}\r
#include<strsafe.h>\r
#include<krb5.h>\r
\r
+#ifdef DEBUG\r
+#include<assert.h>\r
+#endif\r
+\r
khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;\r
khm_boolean krb5_initialized = FALSE;\r
khm_handle krb5_credset = NULL;\r
}\r
\r
if(k5_main_fiber != NULL) {\r
-#if (_WIN32_WINNT >= 0x0501)\r
- ConvertFiberToThread();\r
+\r
+ if (k5_kinit_fiber) {\r
+#ifdef DEBUG\r
+ assert(k5_kinit_fiber != GetCurrentFiber());\r
+#endif\r
+#if CLEANUP_FIBERS_ON_EXIT\r
+ DeleteFiber(k5_kinit_fiber);\r
+ CloseHandle(k5_kinit_fiber);\r
#endif\r
+ k5_kinit_fiber = NULL;\r
+ }\r
+\r
k5_main_fiber = NULL;\r
+\r
}\r
\r
if(k5_sub != NULL) {\r
extern khm_int32 attr_id_krb5_flags;\r
extern khm_int32 attr_id_krb5_ccname;\r
\r
+extern khm_ui_4 k5_commctl_version;\r
+\r
+#define IS_COMMCTL6() (k5_commctl_version >= 0x60000)\r
+\r
/* Configuration spaces */\r
#define CSNAME_KRB5CRED L"Krb5Cred"\r
#define CSNAME_PARAMS L"Parameters"\r
comctl32.lib \\r
shell32.lib \\r
htmlhelp.lib \\r
- iphlpapi.lib\r
+ iphlpapi.lib \\r
+ shlwapi.lib\r
\r
$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg\r
$(CCSV) $** $@\r
mod.dwSize = sizeof(mod);\r
} while(Module32Next(hsnap, &mod));\r
\r
-#if (_WIN32_WINNT >= 0x501)\r
- /* we are also setting the report style when creating\r
- the control. this is actually optional. */\r
- ListView_SetView(hw, LV_VIEW_DETAILS);\r
-#endif\r
-\r
_done_with_modules:\r
CloseHandle(hsnap);\r
}\r
#ifndef __KHIMAIRA_APPGLOBAL_H\r
#define __KHIMAIRA_APPGLOBAL_H\r
\r
+/* Helpfile */\r
+#define NIDM_HELPFILE L"netidmgr.chm"\r
+\r
/* global data */\r
extern HINSTANCE khm_hInstance;\r
extern int khm_nCmdShow;\r
extern const wchar_t * khm_facility;\r
extern kconf_schema schema_uiconfig[];\r
+extern khm_ui_4 khm_commctl_version;\r
+\r
+#define IS_COMMCTL6() (khm_commctl_version >= 0x60000)\r
\r
typedef struct tag_khm_startup_options {\r
BOOL seen;\r
void khm_parse_commandline();\r
void khm_register_window_classes(void);\r
\r
+HWND khm_html_help(HWND hwnd, UINT command, DWORD_PTR data);\r
+\r
#define MAX_RES_STRING 1024\r
\r
#define ELIPSIS L"..."\r
cfg_idents.idents[i].lv_idx = ListView_InsertItem(hw, &lvi);\r
}\r
\r
-#if (_WIN32_WINNT >= 0x501)\r
- ListView_SetView(hw, LV_VIEW_DETAILS);\r
-#endif\r
}\r
return FALSE;\r
\r
hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS);\r
#ifdef DEBUG\r
assert(hw);\r
-#endif\r
-#if (_WIN32_WINNT >= 0x501)\r
- ListView_SetView(hw, LV_VIEW_DETAILS);\r
#endif\r
ZeroMemory(&lvc, sizeof(lvc));\r
\r
\r
/* $Id$ */\r
\r
+#include<shlwapi.h>\r
#include<khmapp.h>\r
\r
#if DEBUG\r
HINSTANCE khm_hInstance;\r
const wchar_t * khm_facility = L"NetIDMgr";\r
int khm_nCmdShow;\r
+khm_ui_4 khm_commctl_version = 0;\r
\r
khm_startup_options khm_startup;\r
\r
ICC_BAR_CLASSES |\r
ICC_DATE_CLASSES |\r
ICC_HOTKEY_CLASS |\r
+ ICC_LISTVIEW_CLASSES |\r
+ ICC_TAB_CLASSES |\r
#if (_WIN32_WINNT >= 0x501)\r
- ICC_LINK_CLASS |\r
- ICC_STANDARD_CLASSES |\r
+ ((IS_COMMCTL6())?\r
+ ICC_LINK_CLASS |\r
+ ICC_STANDARD_CLASSES :\r
+ 0) |\r
#endif\r
- ICC_LISTVIEW_CLASSES |\r
- ICC_TAB_CLASSES;\r
+ 0;\r
+\r
InitCommonControlsEx(&ics);\r
\r
khm_register_main_wnd_class();\r
c->serial);\r
}\r
\r
+static wchar_t helpfile[MAX_PATH] = L"";\r
+\r
+HWND khm_html_help(HWND hwnd, UINT command, DWORD_PTR data) {\r
+ if (!*helpfile) {\r
+ DWORD dw;\r
+ wchar_t ppath[MAX_PATH];\r
+\r
+ dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath));\r
+\r
+ if (dw == 0) {\r
+ StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE);\r
+ } else {\r
+ PathRemoveFileSpec(ppath);\r
+ PathAppend(ppath, NIDM_HELPFILE);\r
+ StringCbCopy(helpfile, sizeof(helpfile), ppath);\r
+ }\r
+ }\r
+\r
+ return HtmlHelp(hwnd, helpfile, command, data);\r
+}\r
+\r
void khm_load_default_modules(void) {\r
kherr_context * c;\r
\r
processes started by plugins. */\r
SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");\r
\r
+ khm_version_init();\r
+\r
+ khm_commctl_version = khm_get_commctl_version(NULL);\r
+\r
/* we only open a main window if this is the only instance \r
of the application that is running. */\r
kmq_init();\r
break;\r
\r
case KHUI_ACTION_HELP_CTX:\r
- HtmlHelp(khm_hwnd_main, NIDM_HELPFILE,\r
- HH_HELP_CONTEXT, IDH_WELCOME);\r
+ khm_html_help(khm_hwnd_main, HH_HELP_CONTEXT, IDH_WELCOME);\r
break;\r
\r
case KHUI_ACTION_HELP_CONTENTS:\r
- HtmlHelp(khm_hwnd_main, NIDM_HELPFILE,\r
- HH_DISPLAY_TOC, 0);\r
+ khm_html_help(khm_hwnd_main, HH_DISPLAY_TOC, 0);\r
break;\r
\r
case KHUI_ACTION_HELP_INDEX:\r
- HtmlHelp(khm_hwnd_main, NIDM_HELPFILE,\r
- HH_DISPLAY_INDEX, (DWORD_PTR) L"");\r
+ khm_html_help(khm_hwnd_main, HH_DISPLAY_INDEX, (DWORD_PTR) L"");\r
break;\r
\r
case KHUI_ACTION_HELP_ABOUT:\r
khm_create_about_window();\r
break;\r
\r
+ case KHUI_ACTION_IMPORT:\r
+ khm_cred_import();\r
+ break;\r
+\r
case KHUI_ACTION_PROPERTIES:\r
/* properties are not handled by the main window.\r
Just bounce it to credwnd. However, use SendMessage\r
\r
wcx.cbSize = sizeof(wcx);\r
wcx.style =\r
+ CS_OWNDC |\r
#if(_WIN32_WINNT >= 0x0501)\r
- CS_DROPSHADOW |\r
+ ((IS_COMMCTL6())? CS_DROPSHADOW: 0) |\r
#endif\r
- CS_OWNDC;\r
+ 0;\r
wcx.lpfnWndProc = alerter_wnd_proc;\r
wcx.cbClsExtra = 0;\r
wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);\r
khm_reqdaemon_thread_proc(LPVOID vparam) {\r
BOOL rv;\r
MSG msg;\r
+#ifdef DEBUG\r
DWORD dw;\r
-\r
+#endif\r
khm_register_reqdaemonwnd_class();\r
\r
#ifdef DEBUG\r
$(OBJ)\actiondef.obj \\r
$(OBJ)\acceldef.obj \\r
$(OBJ)\configui.obj \\r
- $(OBJ)\trackerwnd.obj\r
+ $(OBJ)\trackerwnd.obj \\r
+ $(OBJ)\version.obj\r
\r
INCFILES= \\r
$(INCDIR)\khuidefs.h \\r
\r
#include<strsafe.h>\r
\r
+/*! \internal */\r
+KHMEXP void KHMAPI\r
+khm_version_init(void);\r
+\r
/*! \defgroup khui User Interface\r
\r
Functions and data structures for interacting with the user\r
interface.\r
\r
-*/\r
+@{*/\r
+\r
+/*! \brief Get the version of the NetIDMgr library\r
+\r
+ \param[out] libver Receives the version of the library.\r
+\r
+ \param[out] apiver Receives the API version of the library.\r
+ Optional. Set to NULL if this value is not required.\r
+\r
+ \note When the NetIDMgr framework loads a plugin, it checks the\r
+ version information of the plugin against the version of the\r
+ library to determine if the plugin is compatible.\r
+ */\r
+KHMEXP void KHMAPI\r
+khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver);\r
+\r
+/*! \brief Return the version of Common Control library\r
+\r
+ Can be used to check the version of the Windows Common Control\r
+ library that is currently loaded. The return value of the\r
+ function is the packed version value obatained by the macro :\r
+\r
+ \code\r
+ MAKELONG(vesion->dwMinorVersion, version->dwMajorVersion);\r
+ \endcode\r
+\r
+ The \a pdvi parameter is optional. Specify NULL if this is not\r
+ required.\r
+ */\r
+KHMEXP khm_ui_4 KHMAPI\r
+khm_get_commctl_version(khm_version * pdvi);\r
+\r
+/*!@}*/\r
\r
#endif\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<shlwapi.h>\r
+#include<khuidefs.h>\r
+#include<netidmgr_intver.h>\r
+\r
+DLLVERSIONINFO ver_commctl;\r
+\r
+static void\r
+get_dll_version(wchar_t * dllname, DLLVERSIONINFO * pdvi) {\r
+ HINSTANCE hdll;\r
+\r
+ hdll = LoadLibrary(dllname);\r
+\r
+ ZeroMemory(pdvi, sizeof(*pdvi));\r
+\r
+ if(hdll) {\r
+ DLLGETVERSIONPROC pDllGetVersion;\r
+\r
+ pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hdll, "DllGetVersion");\r
+ if(pDllGetVersion) {\r
+ pdvi->cbSize = sizeof(*pdvi);\r
+\r
+ (*pDllGetVersion)(pdvi);\r
+ }\r
+ FreeLibrary(hdll);\r
+ }\r
+}\r
+\r
+KHMEXP void KHMAPI\r
+khm_version_init(void) {\r
+ get_dll_version(L"comctl32.dll", &ver_commctl);\r
+}\r
+\r
+KHMEXP void KHMAPI\r
+khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver) {\r
+ if (!libver)\r
+ return;\r
+\r
+ libver->major = KH_VERSION_MAJOR;\r
+ libver->minor = KH_VERSION_MINOR;\r
+ libver->patch = KH_VERSION_PATCH;\r
+ libver->aux = KH_VERSION_AUX;\r
+\r
+ if (apiver)\r
+ *apiver = KH_VERSION_API;\r
+}\r
+\r
+KHMEXP khm_ui_4 KHMAPI\r
+khm_get_commctl_version(khm_version * pdvi) {\r
+ if (pdvi) {\r
+ pdvi->major = (khm_ui_2) ver_commctl.dwMajorVersion;\r
+ pdvi->minor = (khm_ui_2) ver_commctl.dwMinorVersion;\r
+ pdvi->patch = (khm_ui_2) ver_commctl.dwBuildNumber;\r
+ pdvi->aux = (khm_ui_2) ver_commctl.dwPlatformID;\r
+ }\r
+\r
+ return MAKELONG(ver_commctl.dwMinorVersion, ver_commctl.dwMajorVersion);\r
+}\r