summaryrefslogtreecommitdiffstats
path: root/src/windows/identity/kmm
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2005-11-29 22:05:23 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2005-11-29 22:05:23 +0000
commita15641c1710ccb204f6dc66c539c42b7617a2ea9 (patch)
tree747a531f34cc909a1f30f91893366e4ac4d99ffc /src/windows/identity/kmm
parent52e7daa850554e507f7df50e77041fd67ddbcca1 (diff)
downloadkrb5-a15641c1710ccb204f6dc66c539c42b7617a2ea9.tar.gz
krb5-a15641c1710ccb204f6dc66c539c42b7617a2ea9.tar.xz
krb5-a15641c1710ccb204f6dc66c539c42b7617a2ea9.zip
KFW Network Identity Manager (Beta 2)
All features completed except for: * Debug Window * KRB5.INI (aka Realm) Editor * Column Selection * Graphics are incomplete * Documentation is incomplete ticket: new status: resolved component: windows target_version: 1.4.4 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17516 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/identity/kmm')
-rw-r--r--src/windows/identity/kmm/kmm.c43
-rw-r--r--src/windows/identity/kmm/kmm.h68
-rw-r--r--src/windows/identity/kmm/kmm_module.c396
-rw-r--r--src/windows/identity/kmm/kmm_plugin.c66
-rw-r--r--src/windows/identity/kmm/kmm_reg.c54
-rw-r--r--src/windows/identity/kmm/kmm_registrar.c196
-rw-r--r--src/windows/identity/kmm/kmmconfig.csv15
-rw-r--r--src/windows/identity/kmm/kmminternal.h59
-rw-r--r--src/windows/identity/kmm/kmmmain.c10
-rw-r--r--src/windows/identity/kmm/kplugin.h2
-rw-r--r--src/windows/identity/kmm/lang/kmm_msgs.mc68
11 files changed, 750 insertions, 227 deletions
diff --git a/src/windows/identity/kmm/kmm.c b/src/windows/identity/kmm/kmm.c
index af8419fdaa..5e955953df 100644
--- a/src/windows/identity/kmm/kmm.c
+++ b/src/windows/identity/kmm/kmm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -25,13 +25,37 @@
/* $Id$ */
#include<kmminternal.h>
+#include<assert.h>
-khm_boolean kmm_load_locale_lib(kmm_module_i * m, kmm_module_locale * l)
+khm_boolean kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l)
{
HMODULE h;
if(l->filename != NULL) {
- h = LoadLibrary(l->filename);
+ wchar_t path[MAX_PATH];
+ DWORD dw;
+
+ /* construct the path name */
+ assert(m->h_module != NULL);
+
+ dw = PathIsFileSpec(l->filename);
+
+ assert(dw);
+ if (!dw)
+ return FALSE;
+
+ dw = GetModuleFileName(m->h_module, path, ARRAYLENGTH(path));
+ assert(dw != 0);
+ if (dw == 0)
+ return FALSE;
+
+ PathRemoveFileSpec(path);
+ dw = PathAppend(path, l->filename);
+ assert(dw);
+ if (!dw)
+ return FALSE;
+
+ h = LoadLibrary(path);
if(!h)
return FALSE;
@@ -41,6 +65,7 @@ khm_boolean kmm_load_locale_lib(kmm_module_i * m, kmm_module_locale * l)
LeaveCriticalSection(&cs_kmm);
return TRUE;
+
} else {
/* in this case, the language resources are assumed to be in the
main module library itself. */
@@ -69,9 +94,9 @@ KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale
return KHM_ERROR_INVALID_OPERATION;
if(!locales || n_locales < 0)
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
- f = malloc(n_locales * sizeof(int));
+ f = PMALLOC(n_locales * sizeof(int));
if(!f)
return KHM_ERROR_UNKNOWN;
ZeroMemory(f, sizeof(int) * n_locales);
@@ -82,7 +107,7 @@ KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale
for(i=0; i<n_locales; i++) {
if(locales[i].language == lcid) {
f[i] = TRUE;
- if(kmm_load_locale_lib(m, &locales[i]))
+ if(kmmint_load_locale_lib(m, &locales[i]))
break;
}
}
@@ -94,7 +119,7 @@ KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale
for(i=0; i<n_locales; i++) {
if(!f[i] && (PRIMARYLANGID(locales[i].language) == PRIMARYLANGID(lcid))) {
f[i] = TRUE;
- if(kmm_load_locale_lib(m,&locales[i]))
+ if(kmmint_load_locale_lib(m,&locales[i]))
break;
}
}
@@ -106,7 +131,7 @@ KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale
for(i=0; i<n_locales; i++) {
if(!f[i] && (locales[i].flags & KMM_MLOC_FLAG_DEFAULT)) {
f[i] = TRUE;
- if(kmm_load_locale_lib(m,&locales[i]))
+ if(kmmint_load_locale_lib(m,&locales[i]))
break;
}
}
@@ -118,7 +143,7 @@ KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale
rv = KHM_ERROR_NOT_FOUND;
_exit:
- free(f);
+ PFREE(f);
return rv;
}
diff --git a/src/windows/identity/kmm/kmm.h b/src/windows/identity/kmm/kmm.h
index 8e487be73a..0dc7e4cea4 100644
--- a/src/windows/identity/kmm/kmm.h
+++ b/src/windows/identity/kmm/kmm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -54,7 +54,19 @@ typedef khm_handle kmm_plugin;
#define KMM_MAXCCH_DESC 512
/*! \brief Maximum number of bytes in a description in KMM including the terminating NULL */
-#define KMM_MAXCB_DESC (sizeof(wchar_t) * KMM_MAXCB_NAME)
+#define KMM_MAXCB_DESC (sizeof(wchar_t) * KMM_MAXCCH_NAME)
+
+/*! \brief Maximum number of characters in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCCH_VENDOR 256
+
+/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCB_VENDOR (sizeof(wchar_t) * KMM_MAXCCH_VENDOR)
+
+/*! \brief Maximum number of characters in a support URI in KMM including the terminating NULL */
+#define KMM_MAXCCH_SUPPORT 256
+
+/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */
+#define KMM_MAXCB_SUPPORT (sizeof(wchar_t) * KMM_MAXCCH_SUPPORT)
/*! \brief Maximum number of dependencies per plugin
*/
@@ -62,7 +74,7 @@ typedef khm_handle kmm_plugin;
/*! \brief Maximum number of dependants per plugin
*/
-#define KMM_MAX_DEPENDANTS 16
+#define KMM_MAX_DEPENDANTS 32
/*! \brief Maximum number of characters a dependency string including trailing double NULL */
#define KMM_MAXCCH_DEPS (KMM_MAXCCH_NAME * KMM_MAX_DEPENDENCIES + 1)
@@ -141,23 +153,27 @@ typedef struct tag_kmm_plugin_info {
/*! \brief A credentials provider
\see \ref pi_pt_cred for more information.
-*/
+ */
#define KHM_PITYPE_CRED 1
+/*! \brief A identity provider
+
+ \see \ref pi_pt_cred for more information
+ */
+#define KHM_PITYPE_IDENT 2
+
/*! \brief A configuration provider
\see \ref pi_pt_conf for more information.
-*/
-#define KHM_PITYPE_CONFIG 2
+ */
+#define KHM_PITYPE_CONFIG 3
-/*@}*/
+/*! \brief Undefined plugin type
-/*! \name Plugin flags
-@{*/
+ The plugin doesn't provide any credential type.
+ */
+#define KHM_PITYPE_MISC 4
-/*! \brief The plugin is an identity provider
-*/
-#define KHM_PIFLAG_IDENTITY_PROVIDER 1
/*@}*/
/*! \brief Plugin states */
@@ -208,6 +224,8 @@ typedef struct tag_kmm_module_reg {
wchar_t * vendor; /*!< Vendor/copyright string */
+ wchar_t * support; /*!< Support URL/contact */
+
khm_int32 n_plugins; /*!< Number of plugins that are
active */
kmm_plugin_reg * plugin_reg_info; /*!< Array of kmm_plugin_reg
@@ -243,6 +261,12 @@ typedef struct tag_kmm_module_info {
/*! \brief Module states
*/
enum KMM_MODULE_STATES {
+ KMM_MODULE_STATE_FAIL_INCOMPAT=-12, /*!< The library containing
+ the module was not
+ compatible with this version
+ of NetIDMgr. */
+ KMM_MODULE_STATE_FAIL_INV_MODULE=-11, /*!< The library containing
+ the module was invalid. */
KMM_MODULE_STATE_FAIL_UNKNOWN=-10, /*!< Module could not be
loaded due to unknown
reasons. */
@@ -463,14 +487,14 @@ KHMEXP khm_boolean KHMAPI
kmm_load_pending(void);
#ifdef _WIN32
-/*! \brief Returns the Windows module handle from a handle to a NetIDMgr module.
+/*! \brief Returns the Windows module handle from a handle to a NetIDMgr module.
Although it is possible to obtain the Windows module handle and
use it to call Windows API functions, it is not recommended to do
so. This is because that might cause the state of the module to
change in ways which are inconsistent from the internal data
structures that kmm maintains.
-*/
+ */
KHMEXP HMODULE KHMAPI
kmm_get_hmodule(kmm_module m);
#endif
@@ -526,7 +550,7 @@ kmm_release_plugin(kmm_plugin p);
\retval KHM_ERROR_SUCCESS Succeeded.
\retval KHM_ERROR_INVALID_OPERATION The function was not called
during init_module()
- \retval KHM_ERROR_INVALID_PARM One or more parameters were invalid
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid
\retval KHM_ERROR_DUPLICATE The plugin was already provided
\note This can only be called when handing init_module()
@@ -661,7 +685,7 @@ kmm_get_modules_config(khm_int32 flags, khm_handle * result);
copied.
\retval KHM_ERROR_SUCCESS The requested information was copied
- \retval KHM_ERROR_INVALID_PARM One of the parameters was invalid
+ \retval KHM_ERROR_INVALID_PARAM One of the parameters was invalid
\retval KHM_ERROR_TOO_LONG The buffer was not large enough or was
NULL. The number of bytes requied is in \a cb_buffer.
\retval KHM_ERROR_NOT_FOUND The specified module is not a
@@ -720,7 +744,7 @@ kmm_release_module_info_i(kmm_module_info * info);
\retval KHM_ERROR_TOO_LONG The buffer was either \a NULL or
insufficient to hold the requested information. The required
size of the buffer was stored in \a cb_buffer
- \retval KHM_ERROR_INVALID_PARM One or more parameters were
+ \retval KHM_ERROR_INVALID_PARAM One or more parameters were
invlaid.
\retval KHM_ERROR_NOT_FOUND The specified plugin was not found
among the registered plugins.
@@ -821,9 +845,9 @@ kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags);
zero, in which case \a plugin_info can be \a NULL. Plugins can be
registered separately using kmm_register_plugin().
- \param[in] module Information about the module. All members are
- required, however \a plugin_info can be \a NULL if \a
- n_plugins is zero.
+ \param[in] module Information about the module. The name and path
+ fields are required. The \a plugin_info field can only be \a
+ NULL if \a n_plugins is zero.
\param[in] config_flags Flags used to call khc_open_space(). This
can be used to choose the configuration store in which the
@@ -911,6 +935,10 @@ typedef struct tag_kmm_module_locale {
kmm_get_resource_hmodule(). This function does not return until a
matched library is loaded.
+ Note that the ::kmm_module_locale structure only specifies a
+ module name for the resource module. This resource module must
+ exist in the same directory as the \a module.
+
\param[in] module The module handle
\param[in] locales An array of ::kmm_module_locale objects
\param[in] n_locales The number of objects in the array pointed to by \a locales
diff --git a/src/windows/identity/kmm/kmm_module.c b/src/windows/identity/kmm/kmm_module.c
index e1f5292ce8..25da22345b 100644
--- a/src/windows/identity/kmm/kmm_module.c
+++ b/src/windows/identity/kmm/kmm_module.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -25,8 +25,10 @@
/* $Id$ */
#include<kmminternal.h>
+#include<netidmgr_version.h>
+#include<assert.h>
-kmm_module_i * kmm_get_module_i(wchar_t * name)
+kmm_module_i * kmmint_get_module_i(wchar_t * name)
{
kmm_module_i * m;
size_t sz;
@@ -39,11 +41,11 @@ kmm_module_i * kmm_get_module_i(wchar_t * name)
m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name);
if(m == NULL) {
- m = malloc(sizeof(kmm_module_i));
+ m = PMALLOC(sizeof(kmm_module_i));
ZeroMemory(m, sizeof(kmm_module_i));
m->magic = KMM_MODULE_MAGIC;
- m->name = malloc(sz);
+ m->name = PMALLOC(sz);
StringCbCopy(m->name, sz, name);
m->state = KMM_MODULE_STATE_NONE;
@@ -55,7 +57,7 @@ kmm_module_i * kmm_get_module_i(wchar_t * name)
return m;
}
-kmm_module_i * kmm_find_module_i(wchar_t * name)
+kmm_module_i * kmmint_find_module_i(wchar_t * name)
{
kmm_module_i * m;
@@ -67,7 +69,7 @@ kmm_module_i * kmm_find_module_i(wchar_t * name)
}
/* called with cs_kmm held */
-void kmm_free_module(kmm_module_i * m)
+void kmmint_free_module(kmm_module_i * m)
{
m->magic = 0;
@@ -75,14 +77,24 @@ void kmm_free_module(kmm_module_i * m)
LDELETE(&kmm_all_modules, m);
if (m->name)
- free(m->name);
+ PFREE(m->name);
+
+ if (m->description)
+ PFREE(m->description);
+
if (m->path)
- free(m->path);
+ PFREE(m->path);
+
if (m->vendor)
- free(m->vendor);
+ PFREE(m->vendor);
+
+ if (m->support)
+ PFREE(m->support);
+
if (m->version_info)
- free(m->version_info);
- free(m);
+ PFREE(m->version_info);
+
+ PFREE(m);
if (kmm_all_modules == NULL)
SetEvent(evt_exit);
@@ -91,7 +103,7 @@ void kmm_free_module(kmm_module_i * m)
KHMEXP khm_int32 KHMAPI kmm_hold_module(kmm_module module)
{
if(!kmm_is_module(module))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
kmm_module_from_handle(module)->refcount++;
LeaveCriticalSection(&cs_kmm);
@@ -103,7 +115,7 @@ KHMEXP khm_int32 KHMAPI kmm_release_module(kmm_module vm)
{
kmm_module_i * m;
if(!kmm_is_module(vm))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
m = kmm_module_from_handle(vm);
@@ -111,12 +123,313 @@ KHMEXP khm_int32 KHMAPI kmm_release_module(kmm_module vm)
{
/* note that a 0 ref count means that there are no active
plugins */
- kmm_free_module(m);
+ kmmint_free_module(m);
}
LeaveCriticalSection(&cs_kmm);
return KHM_ERROR_SUCCESS;
}
+khm_int32
+kmmint_check_api_version(DWORD v) {
+ /* for now, we require an exact match. In the future when we are
+ swamped with so much time that we don't know what to do with
+ it, we can actually parse the apiversion.txt file and create a
+ compatibility table which we can check against the functions
+ used by the module and decide whether or not it is
+ compatible. */
+
+ if (v != KH_VERSION_API)
+ return KHM_ERROR_INCOMPATIBLE;
+ else
+ return KHM_ERROR_SUCCESS;
+}
+
+struct lang_code {
+ WORD language;
+ WORD codepage;
+};
+
+khm_int32
+kmmint_read_module_info(kmm_module_i * m) {
+ /* the only fields we can count on at this point are m->name and
+ m->path */
+ DWORD t;
+ size_t cb;
+ WORD lang;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ struct lang_code *languages;
+ int n_languages;
+ int i;
+ wchar_t resname[256]; /* the resource names are a lot shorter */
+ wchar_t * r;
+ VS_FIXEDFILEINFO *vff;
+
+ assert(m->name);
+ assert(m->path);
+
+ t = TRUE;
+ cb = GetFileVersionInfoSize(m->path,
+ &t);
+ /* if successful, cb gets the size in bytes of the version info
+ structure and sets t to zero */
+ if (t) {
+ return KHM_ERROR_NOT_FOUND;
+ } else if (cb == 0) {
+ _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
+ return KHM_ERROR_INVALID_PARAM;
+ }
+
+ if (m->version_info) {
+ PFREE(m->version_info);
+ m->version_info = NULL;
+ }
+
+ m->version_info = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->version_info);
+#endif
+
+ if(!GetFileVersionInfo(m->path,
+ t, (DWORD) cb, m->version_info)) {
+ rv = KHM_ERROR_NOT_FOUND;
+ _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path));
+ _location(L"GetFileVersionInfo");
+ goto _cleanup;
+ }
+
+ if(!VerQueryValue(m->version_info,
+ L"\\VarFileInfo\\Translation",
+ (LPVOID*) &languages,
+ &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_NO_TRANS, _dupstr(m->path));
+ _location(L"VerQueryValue");
+ goto _cleanup;
+ }
+
+ n_languages = (int) (cb / sizeof(*languages));
+ lang = GetUserDefaultLangID();
+ for (i = 0; i < n_languages; i++) {
+ if(languages[i].language == lang)
+ break;
+ }
+
+ if (i >= n_languages) {
+ lang = GetSystemDefaultLangID();
+ for (i=0; i<n_languages; i++)
+ if (languages[i].language == lang)
+ break;
+ }
+
+ if (i >= n_languages) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr0(KHERR_WARNING, MSG_RMI_NO_LOCAL);
+ goto _cleanup;
+ }
+
+ /* check module name */
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_MODULE),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_MODULE)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_NAME ||
+ FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_MODULE)));
+ goto _cleanup;
+
+ }
+
+ if (wcscmp(r, m->name)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr2(KHERR_WARNING, MSG_RMI_MOD_MISMATCH,
+ _dupstr(r), _dupstr(m->name));
+ goto _cleanup;
+ }
+
+ /* check API version */
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_APIVER),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_APIVER)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_NAME ||
+ FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_APIVER)));
+ goto _cleanup;
+ }
+
+ t = wcstol(r, NULL, 10);
+
+ rv = kmmint_check_api_version(t);
+
+ if (KHM_FAILED(rv)) {
+ _report_mr2(KHERR_WARNING, MSG_RMI_API_MISMATCH,
+ _int32(t), _int32(KH_VERSION_API));
+ goto _cleanup;
+ }
+
+ /* Looks good. Now load the description, copyright, support URI
+ and file versions */
+ if (m->description) {
+ PFREE(m->description);
+ m->description = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\FileDescription",
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"FileDescription"));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_DESC ||
+ FAILED(StringCbLength(r, KMM_MAXCB_DESC, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(L"FileDescription"));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->description = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->description);
+#endif
+ StringCbCopy(m->description, cb, r);
+
+ /* on to the support URI */
+ if (m->support) {
+ PFREE(m->support);
+ m->support = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_SUPPORT),
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(TEXT(NIMV_SUPPORT)));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_SUPPORT ||
+ FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(TEXT(NIMV_SUPPORT)));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->support = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->support);
+#endif
+ StringCbCopy(m->support, cb, r);
+
+ /* the vendor/copyright */
+ if (m->vendor) {
+ PFREE(m->vendor);
+ m->vendor = NULL;
+ }
+
+ StringCbPrintf(resname, sizeof(resname),
+ L"\\StringFileInfo\\%04x%04x\\LegalCopyright",
+ languages[i].language,
+ languages[i].codepage);
+
+ if (!VerQueryValue(m->version_info,
+ resname, (LPVOID *) &r, &cb)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"LegalCopyright"));
+ goto _cleanup;
+ }
+
+ if (cb > KMM_MAXCB_SUPPORT ||
+ FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG,
+ _cstr(L"LegalCopyright"));
+ goto _cleanup;
+ }
+
+ cb += sizeof(wchar_t);
+
+ m->vendor = PMALLOC(cb);
+#ifdef DEBUG
+ assert(m->vendor);
+#endif
+ StringCbCopy(m->vendor, cb, r);
+
+ if (!VerQueryValue(m->version_info,
+ L"\\",
+ (LPVOID *) &vff,
+ &cb) ||
+ cb != sizeof(*vff)) {
+
+ rv = KHM_ERROR_INVALID_PARAM;
+ _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING,
+ _cstr(L"Fixed Version Info"));
+ goto _cleanup;
+ }
+
+ m->file_version.major = HIWORD(vff->dwFileVersionMS);
+ m->file_version.minor = LOWORD(vff->dwFileVersionMS);
+ m->file_version.patch = HIWORD(vff->dwFileVersionLS);
+ m->file_version.aux = LOWORD(vff->dwFileVersionLS);
+
+ m->prod_version.major = HIWORD(vff->dwProductVersionMS);
+ m->prod_version.minor = LOWORD(vff->dwProductVersionMS);
+ m->prod_version.patch = HIWORD(vff->dwProductVersionLS);
+ m->prod_version.aux = LOWORD(vff->dwProductVersionLS);
+
+ rv = KHM_ERROR_SUCCESS;
+
+ _cleanup:
+ if (KHM_FAILED(rv)) {
+ if (m->version_info) {
+ PFREE(m->version_info);
+ m->version_info = NULL;
+ }
+ }
+
+ return rv;
+}
+
KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
khm_int32 flags,
kmm_module * result)
@@ -127,11 +440,11 @@ KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
khm_int32 rv = KHM_ERROR_SUCCESS;
if(FAILED(StringCbLength(modname, KMM_MAXCB_NAME, &cbsize)))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
cbsize += sizeof(wchar_t);
EnterCriticalSection(&cs_kmm);
- mi = kmm_find_module_i(modname);
+ mi = kmmint_find_module_i(modname);
if(mi != NULL) {
kmm_hold_module(kmm_handle_from_module(mi));
@@ -158,7 +471,7 @@ KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
if(mi) {
m = mi;
} else {
- m = kmm_get_module_i(modname);
+ m = kmmint_get_module_i(modname);
m->state = KMM_MODULE_STATE_PREINIT;
kmm_hold_module(kmm_handle_from_module(m));
}
@@ -215,7 +528,8 @@ KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname,
return rv;
}
-KHMEXP khm_int32 KHMAPI kmm_get_module_state(kmm_module m)
+KHMEXP khm_int32 KHMAPI
+kmm_get_module_state(kmm_module m)
{
if(!kmm_is_module(m))
return KMM_MODULE_STATE_NONE;
@@ -230,7 +544,7 @@ kmm_get_module_info_i(kmm_module vm, kmm_module_info * info) {
EnterCriticalSection(&cs_kmm);
if (!kmm_is_module(vm) || !info)
- rv = KHM_ERROR_INVALID_PARM;
+ rv = KHM_ERROR_INVALID_PARAM;
else {
m = kmm_module_from_handle(vm);
@@ -265,10 +579,11 @@ kmm_release_module_info_i(kmm_module_info * info) {
}
-KHMEXP khm_int32 KHMAPI kmm_unload_module(kmm_module module)
+KHMEXP khm_int32 KHMAPI
+kmm_unload_module(kmm_module module)
{
if(!kmm_is_module(module))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
kmm_hold_module(module);
kmq_post_message(KMSG_KMM,
@@ -279,11 +594,11 @@ KHMEXP khm_int32 KHMAPI kmm_unload_module(kmm_module module)
return KHM_ERROR_SUCCESS;
}
-KHMEXP khm_int32 KHMAPI kmm_load_default_modules(void) {
+KHMEXP khm_int32 KHMAPI
+kmm_load_default_modules(void) {
khm_handle csm = NULL;
+ khm_handle cs_mod = NULL;
khm_int32 rv;
- wchar_t * ll = NULL;
- wchar_t *str;
wchar_t buf[KMM_MAXCCH_NAME];
khm_size s;
@@ -291,44 +606,35 @@ KHMEXP khm_int32 KHMAPI kmm_load_default_modules(void) {
if(KHM_FAILED(rv))
return rv;
- _begin_task(KHERR_CF_TRANSITIVE);
_report_mr0(KHERR_NONE, MSG_LOAD_DEFAULT);
_describe();
- rv = khc_read_multi_string(csm, KMM_VALNAME_LOADLIST, NULL, &s);
- if(rv != KHM_ERROR_TOO_LONG)
- goto _exit;
+ kmmint_add_to_module_queue();
+
+ while(KHM_SUCCEEDED(khc_enum_subspaces(csm, cs_mod, &cs_mod))) {
- ll = malloc(s);
- rv = khc_read_multi_string(csm, KMM_VALNAME_LOADLIST, ll, &s);
- if(KHM_FAILED(rv))
- goto _exit;
+ s = sizeof(buf);
+ if (KHM_FAILED(khc_get_config_space_name(cs_mod, buf, &s)))
+ continue;
- kmmint_add_to_module_queue();
+ /* check for schema subspace. This is not an actual module. */
+ if (!wcscmp(buf, L"_Schema"))
+ continue;
- str = ll;
- while(str && *str) {
- if(SUCCEEDED(StringCbCopy(buf, sizeof(buf), str))) {
- kmm_load_module(buf, 0, NULL);
- }
- str = multi_string_next(str);
+ kmm_load_module(buf, 0, NULL);
}
kmmint_remove_from_module_queue();
-_exit:
- if(ll)
- free(ll);
if(csm)
khc_close_space(csm);
- _end_task();
-
return rv;
}
#ifdef _WIN32
-KHMEXP HMODULE KHMAPI kmm_get_hmodule(kmm_module m)
+KHMEXP HMODULE KHMAPI
+kmm_get_hmodule(kmm_module m)
{
if(!kmm_is_module(m))
return NULL;
diff --git a/src/windows/identity/kmm/kmm_plugin.c b/src/windows/identity/kmm/kmm_plugin.c
index f37eaa186c..b8a90c9fe9 100644
--- a/src/windows/identity/kmm/kmm_plugin.c
+++ b/src/windows/identity/kmm/kmm_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -32,7 +32,7 @@
*/
kmm_plugin_i *
-kmm_get_plugin_i(wchar_t * name)
+kmmint_get_plugin_i(wchar_t * name)
{
kmm_plugin_i * p;
size_t cb;
@@ -45,15 +45,15 @@ kmm_get_plugin_i(wchar_t * name)
p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name);
if(p == NULL) {
- p = malloc(sizeof(kmm_plugin_i));
+ p = PMALLOC(sizeof(kmm_plugin_i));
ZeroMemory(p, sizeof(kmm_plugin_i));
p->magic = KMM_PLUGIN_MAGIC;
- p->p.name = malloc(cb);
+ p->p.name = PMALLOC(cb);
StringCbCopy(p->p.name, cb, name);
p->state = KMM_PLUGIN_STATE_NONE;
hash_add(hash_plugins, (void *) p->p.name, (void *) p);
- kmm_list_plugin(p);
+ kmmint_list_plugin(p);
}
LeaveCriticalSection(&cs_kmm);
@@ -61,7 +61,7 @@ kmm_get_plugin_i(wchar_t * name)
}
kmm_plugin_i *
-kmm_find_plugin_i(wchar_t * name)
+kmmint_find_plugin_i(wchar_t * name)
{
kmm_plugin_i * p;
size_t cb;
@@ -78,7 +78,7 @@ kmm_find_plugin_i(wchar_t * name)
/* the plugin must be delisted before calling this */
void
-kmm_list_plugin(kmm_plugin_i * p)
+kmmint_list_plugin(kmm_plugin_i * p)
{
EnterCriticalSection(&cs_kmm);
if((p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) ||
@@ -92,7 +92,7 @@ kmm_list_plugin(kmm_plugin_i * p)
}
void
-kmm_delist_plugin(kmm_plugin_i * p)
+kmmint_delist_plugin(kmm_plugin_i * p)
{
EnterCriticalSection(&cs_kmm);
if(p->flags & KMM_PLUGIN_FLAG_IN_LIST) {
@@ -112,7 +112,7 @@ kmm_hold_plugin(kmm_plugin p)
kmm_plugin_i * pi;
if(!kmm_is_plugin(p))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
pi = kmm_plugin_from_handle(p);
@@ -124,14 +124,14 @@ kmm_hold_plugin(kmm_plugin p)
/* called with cs_kmm held */
void
-kmm_free_plugin(kmm_plugin_i * pi)
+kmmint_free_plugin(kmm_plugin_i * pi)
{
int i;
pi->magic = 0;
hash_del(hash_plugins, (void *) pi->p.name);
- kmm_delist_plugin(pi);
+ kmmint_delist_plugin(pi);
for(i=0; i<pi->n_dependants; i++) {
kmm_release_plugin(kmm_handle_from_plugin(pi->dependants[i]));
@@ -146,18 +146,18 @@ kmm_free_plugin(kmm_plugin_i * pi)
pi->p.module = NULL;
if(pi->p.name)
- free(pi->p.name);
+ PFREE(pi->p.name);
pi->p.name = NULL;
if(pi->p.description)
- free(pi->p.description);
+ PFREE(pi->p.description);
pi->p.description = NULL;
if(pi->p.dependencies)
- free(pi->p.dependencies);
+ PFREE(pi->p.dependencies);
pi->p.dependencies = NULL;
- free(pi);
+ PFREE(pi);
}
KHMEXP khm_int32 KHMAPI
@@ -167,11 +167,11 @@ kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) {
khm_handle csp_plugin;
if (!info)
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
if (!kmm_is_plugin(p)) {
- rv = KHM_ERROR_INVALID_PARM;
+ rv = KHM_ERROR_INVALID_PARAM;
goto _cleanup;
}
@@ -217,7 +217,7 @@ kmm_release_plugin_info_i(kmm_plugin_info * info) {
khm_int32 rv;
if (!info || !info->h_plugin)
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
rv = kmm_release_plugin(info->h_plugin);
@@ -285,13 +285,13 @@ kmm_release_plugin(kmm_plugin p)
kmm_plugin_i * pi;
if(!kmm_is_plugin(p))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
EnterCriticalSection(&cs_kmm);
pi = kmm_plugin_from_handle(p);
pi->refcount--;
if(pi->refcount == 0) {
- kmm_free_plugin(pi);
+ kmmint_free_plugin(pi);
}
LeaveCriticalSection(&cs_kmm);
@@ -314,20 +314,22 @@ kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
return KHM_ERROR_INVALID_OPERATION;
if(!plugin ||
- FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t), &cb_name)) ||
- (plugin->description &&
- FAILED(StringCbLength(plugin->description, KMM_MAXCB_DESC - sizeof(wchar_t), &cb_desc))) ||
- (plugin->dependencies &&
- KHM_FAILED(multi_string_length_cb(plugin->dependencies, KMM_MAXCB_DEPS, &cb_dep)))
- )
- {
- return KHM_ERROR_INVALID_PARM;
+ FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t),
+ &cb_name)) ||
+ (plugin->description &&
+ FAILED(StringCbLength(plugin->description,
+ KMM_MAXCB_DESC - sizeof(wchar_t),
+ &cb_desc))) ||
+ (plugin->dependencies &&
+ KHM_FAILED(multi_string_length_cb(plugin->dependencies,
+ KMM_MAXCB_DEPS, &cb_dep)))) {
+ return KHM_ERROR_INVALID_PARAM;
}
cb_name += sizeof(wchar_t);
cb_desc += sizeof(wchar_t);
- p = kmm_get_plugin_i(plugin->name);
+ p = kmmint_get_plugin_i(plugin->name);
/* released below or in kmm_init_module() */
kmm_hold_plugin(kmm_handle_from_plugin(p));
@@ -348,13 +350,13 @@ kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
p->p.type = plugin->type;
if(plugin->description) {
- p->p.description = malloc(cb_desc);
+ p->p.description = PMALLOC(cb_desc);
StringCbCopy(p->p.description, cb_desc, plugin->description);
} else
p->p.description = NULL;
if(plugin->dependencies) {
- p->p.dependencies = malloc(cb_dep);
+ p->p.dependencies = PMALLOC(cb_dep);
multi_string_copy_cb(p->p.dependencies, cb_dep, plugin->dependencies);
} else
p->p.dependencies = NULL;
@@ -365,7 +367,7 @@ kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin)
p->state = KMM_PLUGIN_STATE_REG;
- kmm_delist_plugin(p);
+ kmmint_delist_plugin(p);
EnterCriticalSection(&cs_kmm);
LPUSH(&(m->plugins), p);
p->flags |= KMM_PLUGIN_FLAG_IN_MODLIST;
diff --git a/src/windows/identity/kmm/kmm_reg.c b/src/windows/identity/kmm/kmm_reg.c
index ea13fc19bd..131cb75144 100644
--- a/src/windows/identity/kmm/kmm_reg.c
+++ b/src/windows/identity/kmm/kmm_reg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -96,7 +96,7 @@ kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result)
khm_int32 rv;
if(!plugin || wcschr(plugin, L'/') || wcschr(plugin, L'\\'))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
if(KHM_FAILED(kmm_get_plugins_config(flags, &csplugins)))
return KHM_ERROR_UNKNOWN;
@@ -118,7 +118,7 @@ kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result)
khm_int32 rv;
if(!module || wcschr(module, L'/') || wcschr(module, L'\\'))
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
if(KHM_FAILED(kmm_get_modules_config(flags, &csmodules)))
return KHM_ERROR_UNKNOWN;
@@ -143,14 +143,16 @@ kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
config_flags &= ~KHM_FLAG_CREATE;
if((plugin == NULL) ||
- (plugin->dependencies &&
- KHM_FAILED(multi_string_length_cch(plugin->dependencies, KMM_MAXCCH_DEPS, &cch))) ||
- FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME - 1, &cch)) ||
- (plugin->description &&
- FAILED(StringCchLength(plugin->description, KMM_MAXCCH_DESC - 1, &cch))) ||
- FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME - 1, &cch)))
+ (plugin->dependencies &&
+ KHM_FAILED(multi_string_length_cch(plugin->dependencies,
+ KMM_MAXCCH_DEPS, &cch))) ||
+ FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) ||
+ (plugin->description &&
+ FAILED(StringCchLength(plugin->description,
+ KMM_MAXCCH_DESC, &cch))) ||
+ FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch)))
{
- return KHM_ERROR_INVALID_PARM;
+ return KHM_ERROR_INVALID_PARAM;
}
/* note that we are retaining the length of the plugin name in
@@ -177,10 +179,13 @@ kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
rv = khc_write_string(csp_plugin, L"Description", plugin->description);
CKRV;
}
+
if(plugin->dependencies) {
- rv = khc_write_multi_string(csp_plugin, L"Dependencies", plugin->dependencies);
+ rv = khc_write_multi_string(csp_plugin, L"Dependencies",
+ plugin->dependencies);
CKRV;
}
+
rv = khc_write_int32(csp_plugin, L"Type", plugin->type);
CKRV;
rv = khc_write_int32(csp_plugin, L"Flags", plugin->flags);
@@ -198,12 +203,12 @@ kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
cb += cch * sizeof(wchar_t);
scb = cb;
- pl = malloc(cb);
+ pl = PMALLOC(cb);
- rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb);
+ rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb);
if(KHM_FAILED(rv)) {
if(pl)
- free(pl);
+ PFREE(pl);
goto _exit;
}
@@ -212,7 +217,7 @@ kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags)
rv = khc_write_multi_string(csp_module, L"PluginList", pl);
}
- free(pl);
+ PFREE(pl);
CKRV;
}
@@ -236,24 +241,21 @@ kmm_register_module(kmm_module_reg * module, khm_int32 config_flags)
int i;
if((module == NULL) ||
- FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME - 1, &cch)) ||
+ FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME, &cch)) ||
(module->description &&
- FAILED(StringCchLength(module->description, KMM_MAXCCH_DESC - 1, &cch))) ||
+ FAILED(StringCchLength(module->description,
+ KMM_MAXCCH_DESC, &cch))) ||
FAILED(StringCchLength(module->path, MAX_PATH, &cch)) ||
- (module->n_plugins > 0 && module->plugin_reg_info == NULL))
- {
- return KHM_ERROR_INVALID_PARM;
+ (module->n_plugins > 0 && module->plugin_reg_info == NULL)) {
+ return KHM_ERROR_INVALID_PARAM;
}
#define CKRV if(KHM_FAILED(rv)) goto _exit
- rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE, &csp_module);
+ rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE,
+ &csp_module);
CKRV;
- if(module->description) {
- rv = khc_write_string(csp_module, L"Description", module->description);
- CKRV;
- }
rv = khc_write_string(csp_module, L"ImagePath", module->path);
CKRV;
@@ -264,7 +266,7 @@ kmm_register_module(kmm_module_reg * module, khm_int32 config_flags)
is loaded for the first time */
for(i=0; i<module->n_plugins; i++) {
- rv = kmm_register_plugin(module->plugin_reg_info + i, config_flags);
+ rv = kmm_register_plugin(&(module->plugin_reg_info[i]), config_flags);
CKRV;
}
diff --git a/src/windows/identity/kmm/kmm_registrar.c b/src/windows/identity/kmm/kmm_registrar.c
index 3c690f36b6..ae94a9ed31 100644
--- a/src/windows/identity/kmm/kmm_registrar.c
+++ b/src/windows/identity/kmm/kmm_registrar.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -38,6 +38,9 @@ kmmint_check_completion(void) {
InterlockedIncrement(&startup_signal) == 1) {
load_done = TRUE;
+
+ /* TODO: check for orphaned plugins */
+
kmq_post_message(KMSG_KMM, KMSG_KMM_I_DONE, 0, 0);
}
}
@@ -148,31 +151,35 @@ DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)
p->tid_thread = GetCurrentThreadId();
- rv = (p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_INIT, 0, (void *) &(p->p)));
+ if (IsBadCodePtr(p->p.msg_proc)) {
+ rv = KHM_ERROR_INVALID_PARAM;
+ } else {
+ rv = (p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_INIT,
+ 0, (void *) &(p->p)));
+ }
/* if it fails to initialize, we exit the plugin */
if(KHM_FAILED(rv)) {
- kmmint_remove_from_plugin_queue();
+ kmmint_remove_from_plugin_queue();
rv = 1;
goto _exit;
}
/* subscribe to default message classes by plugin type */
- if(p->p.type & KHM_PITYPE_CRED) {
+ if(p->p.type == KHM_PITYPE_CRED) {
kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
kmq_subscribe(KMSG_CRED, p->p.msg_proc);
- }
-
- if(p->p.flags & KHM_PIFLAG_IDENTITY_PROVIDER) {
+ } else if(p->p.type == KHM_PITYPE_IDENT) {
khm_handle h = NULL;
+ kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc);
+ kmq_subscribe(KMSG_KCDB, p->p.msg_proc);
+
kmq_create_subscription(p->p.msg_proc, &h);
kcdb_identity_set_provider(h);
/* kcdb deletes the subscription when it's done with it */
- }
-
- if(p->p.type == KHM_PITYPE_CONFIG) {
+ } else if(p->p.type == KHM_PITYPE_CONFIG) {
/*TODO: subscribe to configuration provider messages here */
}
@@ -204,17 +211,15 @@ DWORD WINAPI kmm_plugin_broker(LPVOID lpParameter)
while(KHM_SUCCEEDED(kmq_dispatch(INFINITE)));
/* unsubscribe from default message classes by plugin type */
- if(p->p.type & KHM_PITYPE_CRED) {
+ if(p->p.type == KHM_PITYPE_CRED) {
kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
kmq_unsubscribe(KMSG_CRED, p->p.msg_proc);
- }
-
- if(p->p.flags & KHM_PIFLAG_IDENTITY_PROVIDER) {
+ } else if (p->p.type == KHM_PITYPE_IDENT) {
+ kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc);
+ kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc);
kcdb_identity_set_provider(NULL);
- }
-
- if(p->p.type == KHM_PITYPE_CONFIG) {
+ } else if(p->p.type == KHM_PITYPE_CONFIG) {
/*TODO: unsubscribe from configuration provider messages here */
}
@@ -224,7 +229,8 @@ _exit:
p->state = KMM_PLUGIN_STATE_EXITED;
/* the following call will automatically release the plugin */
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p);
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
+ KMM_REG_EXIT_PLUGIN, (void *) p);
TlsSetValue(tls_kmm, (LPVOID) 0);
@@ -282,8 +288,7 @@ void kmm_init_plugin(kmm_plugin_i * p) {
}
if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin)) ||
- KHM_FAILED(khc_read_int32(csp_plugin, L"Flags", &t)))
- {
+ KHM_FAILED(khc_read_int32(csp_plugin, L"Flags", &t))) {
if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) {
_report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED);
@@ -329,13 +334,15 @@ void kmm_init_plugin(kmm_plugin_i * p) {
wchar_t * d;
khm_size sz = 0;
- if(khc_read_multi_string(csp_plugin, L"Dependencies", NULL, &sz) != KHM_ERROR_TOO_LONG)
+ if(khc_read_multi_string(csp_plugin, L"Dependencies",
+ NULL, &sz) != KHM_ERROR_TOO_LONG)
break;
- deps = malloc(sz);
- if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies", deps, &sz))) {
+ deps = PMALLOC(sz);
+ if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies",
+ deps, &sz))) {
if(deps)
- free(deps);
+ PFREE(deps);
break;
}
@@ -343,14 +350,14 @@ void kmm_init_plugin(kmm_plugin_i * p) {
kmm_plugin_i * pd;
int i;
- pd = kmm_get_plugin_i(d);
+ pd = kmmint_get_plugin_i(d);
if(pd->state == KMM_PLUGIN_STATE_NONE) {
/* the dependant was not previously known */
pd->state = KMM_PLUGIN_STATE_PLACEHOLDER;
}
- for(i=0; i<pd->n_dependants; i++) {
+ for(i=0; i < pd->n_dependants; i++) {
if(pd->dependants[i] == p)
break;
}
@@ -361,7 +368,7 @@ void kmm_init_plugin(kmm_plugin_i * p) {
RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
- /* released in kmm_free_plugin() */
+ /* released in kmmint_free_plugin() */
kmm_hold_plugin(kmm_handle_from_plugin(p));
pd->dependants[pd->n_dependants] = p;
pd->n_dependants++;
@@ -378,15 +385,15 @@ void kmm_init_plugin(kmm_plugin_i * p) {
p->state = KMM_PLUGIN_STATE_HOLD;
}
- free(deps);
+ PFREE(deps);
} while(FALSE);
LeaveCriticalSection(&cs_kmm);
EnterCriticalSection(&cs_kmm);
p->module->plugin_count++;
- kmm_delist_plugin(p);
- kmm_list_plugin(p);
+ kmmint_delist_plugin(p);
+ kmmint_list_plugin(p);
LeaveCriticalSection(&cs_kmm);
if(p->state == KMM_PLUGIN_STATE_HOLD) {
@@ -397,13 +404,12 @@ void kmm_init_plugin(kmm_plugin_i * p) {
kmmint_add_to_plugin_queue();
- p->ht_thread = CreateThread(
- NULL,
- 0,
- kmm_plugin_broker,
- (LPVOID) p,
- CREATE_SUSPENDED,
- &dummy);
+ p->ht_thread = CreateThread(NULL,
+ 0,
+ kmm_plugin_broker,
+ (LPVOID) p,
+ CREATE_SUSPENDED,
+ &dummy);
p->state = KMM_PLUGIN_STATE_INIT;
@@ -549,18 +555,19 @@ void kmm_init_module(kmm_module_i * m) {
goto _exit;
}
- if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Flags", &i))) {
- if(i & KMM_MODULE_FLAG_DISABLED) {
- _report_mr0(KHERR_ERROR, MSG_IM_DISABLED);
+ if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Flags", &i)) &&
+ (i & KMM_MODULE_FLAG_DISABLED)) {
- m->state = KMM_MODULE_STATE_FAIL_DISABLED;
- goto _exit;
- }
+ _report_mr0(KHERR_ERROR, MSG_IM_DISABLED);
+
+ m->state = KMM_MODULE_STATE_FAIL_DISABLED;
+ goto _exit;
}
if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) {
khm_int64 tm;
khm_int64 ct;
+ khm_int32 last_reason = 0;
/* reset the failure count if the failure count reset time
period has elapsed */
@@ -578,7 +585,13 @@ void kmm_init_module(kmm_module_i * m) {
}
- if(i > max_fail_count) {
+ khc_read_int32(csp_mod, L"FailureReason", &last_reason);
+
+ /* did we exceed the max failure count? However, we ignore
+ the max failure count if the reason why it didn't load the
+ last time was because the module wasn't found. */
+ if(i > max_fail_count &&
+ last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) {
/* failed too many times */
_report_mr0(KHERR_ERROR, MSG_IM_MAX_FAIL);
@@ -587,10 +600,11 @@ void kmm_init_module(kmm_module_i * m) {
}
}
- if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) == KHM_ERROR_TOO_LONG) {
+ if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) ==
+ KHM_ERROR_TOO_LONG) {
if(m->path)
- free(m->path);
- m->path = malloc(sz);
+ PFREE(m->path);
+ m->path = PMALLOC(sz);
khc_read_string(csp_mod, L"ImagePath", m->path, &sz);
} else {
_report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED);
@@ -599,11 +613,23 @@ void kmm_init_module(kmm_module_i * m) {
goto _exit;
}
- if (khc_read_string(csp_mod, L"Vendor", NULL, &sz) == KHM_ERROR_TOO_LONG) {
- if (m->vendor)
- free(m->vendor);
- m->vendor = malloc(sz);
- khc_read_string(csp_mod, L"Vendor", m->vendor, &sz);
+ rv = kmmint_read_module_info(m);
+
+ if (KHM_FAILED(rv)) {
+ if (rv == KHM_ERROR_INCOMPATIBLE) {
+ _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE);
+
+ m->state = KMM_MODULE_STATE_FAIL_INCOMPAT;
+ } else if (rv == KHM_ERROR_NOT_FOUND) {
+ _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
+
+ m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
+ } else {
+ _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE);
+
+ m->state = KMM_MODULE_STATE_FAIL_INV_MODULE;
+ }
+ goto _exit;
}
/* check again */
@@ -613,11 +639,13 @@ void kmm_init_module(kmm_module_i * m) {
goto _exit;
}
+ /* from this point on, we must record any failure codes */
+ record_failure = TRUE;
+
hm = LoadLibrary(m->path);
if(!hm) {
m->h_module = NULL;
m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND;
- record_failure = TRUE;
_report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path));
@@ -628,12 +656,11 @@ void kmm_init_module(kmm_module_i * m) {
exit_module */
release_module = FALSE;
exit_module = TRUE;
- record_failure = TRUE;
m->flags |= KMM_MODULE_FLAG_LOADED;
m->h_module = hm;
- /*TODO: check signatures */
+ /* TODO: check signatures */
p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE);
@@ -646,7 +673,6 @@ void kmm_init_module(kmm_module_i * m) {
m->state = KMM_MODULE_STATE_INIT;
-
/* call init_module() */
rv = (*p_init_module)(kmm_handle_from_module(m));
@@ -695,7 +721,7 @@ void kmm_init_module(kmm_module_i * m) {
ResetEvent(evt_exit);
-_exit:
+ _exit:
if(csp_mod) {
if(record_failure) {
khm_int64 ct;
@@ -709,18 +735,18 @@ _exit:
GetSystemTimeAsFileTime((LPFILETIME) &ct);
khc_write_int64(csp_mod, L"FailureTime", ct);
}
+
+ khc_write_int32(csp_mod, L"FailureReason", m->state);
}
khc_close_space(csp_mod);
}
+
if(csp_mods)
khc_close_space(csp_mods);
_report_mr2(KHERR_INFO, MSG_IM_MOD_STATE,
_dupstr(m->name), _int32(m->state));
- if(release_module)
- kmm_release_module(kmm_handle_from_module(m));
-
kmmint_remove_from_module_queue();
/* if something went wrong after init_module was called on the
@@ -728,6 +754,53 @@ _exit:
if(exit_module)
kmm_exit_module(m);
+ if(release_module)
+ kmm_release_module(kmm_handle_from_module(m));
+
+ if (kherr_is_error()) {
+ kherr_context * c;
+ kherr_event * err_e = NULL;
+ kherr_event * warn_e = NULL;
+ kherr_event * e;
+
+ c = kherr_peek_context();
+ err_e = kherr_get_err_event(c);
+ for(e = kherr_get_first_event(c);
+ e;
+ e = kherr_get_next_event(e)) {
+ if (e != err_e &&
+ e->severity == KHERR_WARNING) {
+ warn_e = e;
+ break;
+ }
+ }
+
+ kherr_evaluate_event(err_e);
+ if (warn_e)
+ kherr_evaluate_event(warn_e);
+
+ kherr_clear_error();
+
+ e = kherr_report(KHERR_ERROR,
+ (wchar_t *) MSG_IMERR_TITLE,
+ KHERR_FACILITY,
+ NULL,
+ err_e->long_desc,
+ ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL),
+ KHERR_FACILITY_ID,
+ KHERR_SUGGEST_NONE,
+ _cstr(m->name),
+ ((warn_e)? _cstr(warn_e->long_desc):0),
+ 0,0,
+ KHERR_RF_MSG_SHORT_DESC |
+ ((warn_e)? KHERR_RF_MSG_SUGGEST: 0),
+ KHERR_HMODULE);
+
+ kherr_evaluate_event(e);
+
+ kherr_release_context(c);
+ }
+
_end_task();
}
@@ -780,7 +853,8 @@ void kmm_exit_module(kmm_module_i * m) {
while(p) {
if(p->module == m) {
kmm_hold_plugin(kmm_handle_from_plugin(p));
- kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p);
+ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG,
+ KMM_REG_EXIT_PLUGIN, (void *) p);
np++;
}
diff --git a/src/windows/identity/kmm/kmmconfig.csv b/src/windows/identity/kmm/kmmconfig.csv
index 93444bdf4b..b22e9b2056 100644
--- a/src/windows/identity/kmm/kmmconfig.csv
+++ b/src/windows/identity/kmm/kmmconfig.csv
@@ -9,7 +9,7 @@ PluginManager,KC_SPACE,0,Plugin Manager Configuration
Description,KC_STRING,<Description>,Description of the plugin
Dependencies,KC_STRING,<Dependencies>,Multi string of plugin names of plugins that this plugin depends on
Type,KC_INT32,0,The type of the plugin
- Flags,KC_INT32,0,Flags. Currently unused
+ Flags,KC_INT32,0,Flags
FailureCount,KC_INT32,0,Number of failed loads
FailureTime,KC_INT64,0,FILETIME of first failure
FailureReason,KC_INT32,0,Reason for first failure. One of the plugin status values.
@@ -22,31 +22,24 @@ PluginManager,KC_SPACE,0,Plugin Manager Configuration
ModuleMaxFailureCount,KC_INT32,3,Maximum number of failure counts before module is disabled
ModuleFailureCountResetTime,KC_INT64,72000,Time after first failure at which the failure count is reset
_Schema,KC_SPACE,0,Module schema
- ImagePath,KC_STRING,<Path to the library binary>,Path to the DLL
- Description,KC_STRING,<Description>,Description of the module
- Vendor,KC_STRING,<Vendor string>,Vendor or copyright string
- Flags,KC_INT32,0,Flags. Currently unused.
+ ImagePath,KC_STRING,<Path to the library binary>,Path to the DLL (including DLL name)
+ Flags,KC_INT32,0,Flags
FailureCount,KC_INT32,0,Number of failed loads
FailureTime,KC_INT64,0,FILETIME of first failure
- FailureReason,KC_INT32,0,Reason for first failure. One of the module status values.
- FileVersion,KC_INT64,0,khm_version of file
- ProductVersion,KC_INT64,0,khm_version of product
+ FailureReason,KC_INT32,0,Reason for last failure. One of the module status values.
PluginList,KC_STRING,<plugins>,List of plugins implemented in the module
_Schema,KC_ENDSPACE,0,
OpenAFS,KC_SPACE,0,OpenAFS Module
ImagePath,KC_STRING,afscred.dll,
PluginList,KC_STRING,AfsCred,
- Vendor,KC_STRING,OpenAFS.org,
OpenAFS,KC_ENDSPACE,0,
MITKrb5,KC_SPACE,0,MIT Kerberos V
ImagePath,KC_STRING,krb5cred.dll,
PluginList,KC_STRING,Krb5Cred,
- Vendor,KC_STRING,Massachusetts Institute of Technology,
MITKrb5,KC_ENDSPACE,0,
MITKrb4,KC_SPACE,0,MIT Kerberos IV
ImagePath,KC_STRING,krb4cred.dll,
PluginList,KC_STRING,Krb4Cred,
- Vendor,KC_STRING,Massachusetts Institute of Technology,
MITKrb4,KC_ENDSPACE,0,
Modules,KC_ENDSPACE,0,
PluginManager,KC_ENDSPACE,0,
diff --git a/src/windows/identity/kmm/kmminternal.h b/src/windows/identity/kmm/kmminternal.h
index 662eff228f..3ef45198ef 100644
--- a/src/windows/identity/kmm/kmminternal.h
+++ b/src/windows/identity/kmm/kmminternal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -28,6 +28,7 @@
#define __KHIMAIRA_KMMINTERNAL_H
#include<windows.h>
+#include<shlwapi.h>
#include<strsafe.h>
#define KHERR_FACILITY kmm_facility
@@ -44,7 +45,6 @@
#include<kcreddb.h>
#include<kmm_msgs.h>
-
struct kmm_plugin_i_t; /* forward dcl */
typedef struct kmm_module_i_t {
@@ -52,8 +52,12 @@ typedef struct kmm_module_i_t {
wchar_t * name;
wchar_t * path;
-
+ wchar_t * description;
wchar_t * vendor;
+ wchar_t * support;
+
+ khm_version file_version;
+ khm_version prod_version;
HMODULE h_module;
@@ -80,22 +84,23 @@ typedef struct kmm_module_i_t {
#define kmm_module_from_handle(m) ((kmm_module_i *) m)
#define kmm_handle_from_module(m) ((kmm_module) m)
-/* the resources have been loaded */
-#define KMM_MODULE_FLAG_RES_LOADED 8
-
-/* the signature has been verified */
-#define KMM_MODULE_FLAG_SIG 16
-
/* LoadLibrary succeeded for module */
#define KMM_MODULE_FLAG_LOADED 1
/* init_module entry called */
#define KMM_MODULE_FLAG_INITP 2
+/* the resources have been loaded */
+#define KMM_MODULE_FLAG_RES_LOADED 8
+
+/* the signature has been verified */
+#define KMM_MODULE_FLAG_SIG 16
+
/* the module is disabled by the user
(option specifed in configuration) */
#define KMM_MODULE_FLAG_DISABLED 1024
+
typedef struct kmm_plugin_i_t {
kmm_plugin_reg p;
@@ -182,18 +187,36 @@ void kmm_init_module(kmm_module_i * m);
void kmm_exit_module(kmm_module_i * m);
/* Modules */
-kmm_module_i * kmm_get_module_i(wchar_t * name);
-kmm_module_i * kmm_find_module_i(wchar_t * name);
-void kmm_free_module(kmm_module_i * m);
+kmm_module_i *
+kmmint_get_module_i(wchar_t * name);
+
+kmm_module_i *
+kmmint_find_module_i(wchar_t * name);
+
+void
+kmmint_free_module(kmm_module_i * m);
+
+khm_int32
+kmmint_read_module_info(kmm_module_i * m);
/* Plugins */
-kmm_plugin_i * kmm_get_plugin_i(wchar_t * name);
-kmm_plugin_i * kmm_find_plugin_i(wchar_t * name);
-void kmm_free_plugin(kmm_plugin_i * pi);
-void kmm_list_plugin(kmm_plugin_i * p);
-void kmm_delist_plugin(kmm_plugin_i * p);
+kmm_plugin_i *
+kmmint_get_plugin_i(wchar_t * name);
+
+kmm_plugin_i *
+kmmint_find_plugin_i(wchar_t * name);
+
+void
+kmmint_free_plugin(kmm_plugin_i * pi);
+
+void
+kmmint_list_plugin(kmm_plugin_i * p);
+
+void
+kmmint_delist_plugin(kmm_plugin_i * p);
-khm_boolean kmm_load_locale_lib(kmm_module_i * m, kmm_module_locale * l);
+khm_boolean
+kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l);
#define KMM_CSNAME_ROOT L"PluginManager"
#define KMM_CSNAME_PLUGINS L"Plugins"
diff --git a/src/windows/identity/kmm/kmmmain.c b/src/windows/identity/kmm/kmmmain.c
index 8ec4bc0a3c..6489313f80 100644
--- a/src/windows/identity/kmm/kmmmain.c
+++ b/src/windows/identity/kmm/kmmmain.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -96,9 +96,11 @@ KHMEXP void KHMAPI kmm_exit(void)
kmm_plugin_i * pn;
pn = LNEXT(p);
- /* plugins that were never resolved should be kicked off
- the list. Flipping the refcount will do that if no
- other references exist for the plugin */
+ /* plugins that were never resolved should be kicked off the
+ list. Flipping the refcount will do that if no other
+ references exist for the plugin. The plugins that were
+ waiting for unresolved dependencies will automatically get
+ freed when the placeholders and other plugins get freed. */
if(p->state == KMM_PLUGIN_STATE_PLACEHOLDER) {
kmm_hold_plugin(kmm_handle_from_plugin(p));
kmm_release_plugin(kmm_handle_from_plugin(p));
diff --git a/src/windows/identity/kmm/kplugin.h b/src/windows/identity/kmm/kplugin.h
index f7489bf4c0..99f94f1f4a 100644
--- a/src/windows/identity/kmm/kplugin.h
+++ b/src/windows/identity/kmm/kplugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Massachusetts Institute of Technology
+ * Copyright (c) 2005 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
diff --git a/src/windows/identity/kmm/lang/kmm_msgs.mc b/src/windows/identity/kmm/lang/kmm_msgs.mc
index 5e88121d14..17bc6b80e9 100644
--- a/src/windows/identity/kmm/lang/kmm_msgs.mc
+++ b/src/windows/identity/kmm/lang/kmm_msgs.mc
@@ -73,6 +73,18 @@ Language=English
Module has failed too many times
.
+MessageId=
+SymbolicName=MSG_IM_INVALID_MODULE
+Language=English
+The DLL containing the module was not of the correct format.
+.
+
+MessageId=
+SymbolicName=MSG_IM_INCOMPATIBLE
+Language=English
+The DLL containing the module was not compatible with this version of NetIDMgr.
+.
+
Messageid=
SymbolicName=MSG_IM_NOT_FOUND
Language=English
@@ -104,6 +116,20 @@ Module [%1] is in state [%2!d!]
.
MessageId=
+SymbolicName=MSG_IMERR_TITLE
+Language=English
+Failed to load module %1!s!
+.
+
+MessageId=
+SymbolicName=MSG_IMERR_SUGGEST
+Language=English
+The following information may help resolve this issue:
+
+%2!s!
+.
+
+MessageId=
SymbolicName=MSG_IP_TASK_DESC
Language=English
Initializing plugin [%1]
@@ -144,3 +170,45 @@ SymbolicName=MSG_IP_EXITING
Language=English
The plugin [%1] is in error state [%2!d!]. Exiting plugin.
.
+
+MessageId=
+SymbolicName=MSG_RMI_NOT_FOUND
+Language=English
+Can't get file version information for path [%1!s!]
+.
+
+MessageId=
+SymbolicName=MSG_RMI_NO_TRANS
+Language=English
+Can't get version resource tranlations list for path [%1!s!]
+.
+
+MessageId=
+SymbolicName=MSG_RMI_NO_LOCAL
+Language=English
+The list of version translations were empty or did not contain a resource for the current user or system locale.
+.
+
+MessageId=
+SymbolicName=MSG_RMI_RES_MISSING
+Language=English
+Required resource %1!s! missing
+.
+
+MessageId=
+SymbolicName=MSG_RMI_MOD_MISMATCH
+Language=English
+The module name specified in the resource is [%1!s!] while the module name as registered is [%2!s!]
+.
+
+MessageId=
+SymbolicName=MSG_RMI_RES_TOO_LONG
+Language=English
+The resource %1!s! is malformed or too long
+.
+
+MessageId=
+SymbolicName=MSG_RMI_API_MISMATCH
+Language=English
+The module was compile for API version %1!d!. However the current API version is %2!d!.
+.