From a7eb97b930bbbd3133f336a6f2ccbfb55eebbcfb Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <rgerhards@adiscon.com>
Date: Fri, 29 Feb 2008 16:02:07 +0000
Subject: - added "debug" command to debug environment settings - changed the
 object/interface system to use a new way of calling, giving     up the
 numerical object ID. This was necessary as we needed more     extensibility
 for third-party modules (which don't play at all with the     previous fixed
 object ID). This is stage work for the object loader.     Please note that I
 needed to change the object (de)serializer, I can't     outrule that I have
 introduced bugs there.

---
 conf.c       |  13 ++-
 ctok.c       |   6 +-
 ctok_token.c |   4 +-
 debug.c      |   9 ++-
 expr.c       |  10 +--
 msg.c        |   5 +-
 obj-types.h  |  67 +++++++---------
 obj.c        | 255 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 obj.h        |  12 +--
 queue.c      |  12 ++-
 rsyslog.h    |   2 +
 stream.c     |  20 +++++
 stream.h     |   6 ++
 syslogd.c    |  15 ++--
 sysvar.c     |   4 +-
 var.c        |   2 +-
 vm.c         |   8 +-
 vmop.c       |   4 +-
 vmprg.c      |   4 +-
 vmstk.c      |   4 +-
 wti.c        |   4 +
 wtp.c        |   3 +
 22 files changed, 330 insertions(+), 139 deletions(-)

diff --git a/conf.c b/conf.c
index 1229f1c4..9ac85d34 100644
--- a/conf.c
+++ b/conf.c
@@ -55,6 +55,7 @@
 #include "srUtils.h"
 
 /* static data */
+DEFobjCurrIf(obj)
 DEFobjCurrIf(expr)
 DEFobjCurrIf(ctok)
 #include "vm.h"
@@ -1174,15 +1175,19 @@ cfline(uchar *line, selector_t **pfCurr)
 }
 
 
+/* dummy */
+//static rsRetVal confQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
+
 /* "mimic" a real object - we are currently not one... */
 rsRetVal confClassInit(void)
 {
 	DEFiRet;
 	/* request objects we use */
-	CHKiRet(objUse(expr));
-	CHKiRet(objUse(ctok));
-	CHKiRet(objUse(vm)); // TODO: remove, testing aid! rgerhards, 2008-02-25
-	CHKiRet(objUse(var)); // TODO: remove, testing aid! rgerhards, 2008-02-25
+	CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
+	CHKiRet(objUse(expr, CORE_COMPONENT));
+	CHKiRet(objUse(ctok, CORE_COMPONENT));
+	CHKiRet(objUse(vm, CORE_COMPONENT)); // TODO: remove, testing aid! rgerhards, 2008-02-25
+	CHKiRet(objUse(var, CORE_COMPONENT)); // TODO: remove, testing aid! rgerhards, 2008-02-25
 
 finalize_it:
 	RETiRet;
diff --git a/ctok.c b/ctok.c
index 867a448f..aaffed3b 100644
--- a/ctok.c
+++ b/ctok.c
@@ -573,7 +573,7 @@ CODESTARTobjQueryInterface(ctok)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJctok;
+	//xxxpIf->oID = OBJctok;
 
 	pIf->Construct = ctokConstruct;
 	pIf->ConstructFinalize = ctokConstructFinalize;
@@ -589,8 +589,8 @@ ENDobjQueryInterface(ctok)
 
 BEGINObjClassInit(ctok, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(ctok_token));
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(ctok_token, CORE_COMPONENT));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, ctokConstructFinalize);
 ENDObjClassInit(ctok)
diff --git a/ctok_token.c b/ctok_token.c
index fa21d12c..09200c0f 100644
--- a/ctok_token.c
+++ b/ctok_token.c
@@ -108,7 +108,7 @@ CODESTARTobjQueryInterface(ctok_token)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJctok_token;
+	//xxxpIf->oID = OBJctok_token;
 
 	pIf->Construct = ctok_tokenConstruct;
 	pIf->ConstructFinalize = ctok_tokenConstructFinalize;
@@ -121,7 +121,7 @@ ENDobjQueryInterface(ctok_token)
 
 BEGINObjClassInit(ctok_token, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, ctok_tokenConstructFinalize);
 ENDObjClassInit(ctok_token)
diff --git a/debug.c b/debug.c
index a13f7e61..d1e037f0 100644
--- a/debug.c
+++ b/debug.c
@@ -1152,6 +1152,12 @@ dbgGetRuntimeOptions(void)
 					"filetrace=file (may be provided multiple times)\n"
 					"\nSee debug.html in your doc set or http://www.rsyslog.com for details\n");
 				exit(1);
+			} else if(!strcasecmp((char*)optname, "debug")) {
+				/* this is earlier in the process than the -d option, as such it
+				 * allows us to spit out debug messages from the very beginning.
+				 */
+				Debug = 1;
+				debugging_on = 1;
 			} else if(!strcasecmp((char*)optname, "logfuncflow")) {
 				bLogFuncFlow = 1;
 			} else if(!strcasecmp((char*)optname, "logallocfree")) {
@@ -1176,9 +1182,8 @@ dbgGetRuntimeOptions(void)
 					dbgPrintNameAdd(optval, &printNameFileRoot);
 				}
 			} else {
-				fprintf(stderr, "Error: invalid debug option '%s', value '%s'\n",
+				fprintf(stderr, "Error: invalid debug option '%s', value '%s' - ignored\n",
 					optval, optname);
-				exit(1);
 			}
 		}
 	}
diff --git a/expr.c b/expr.c
index a6b24c88..e6f4ef23 100644
--- a/expr.c
+++ b/expr.c
@@ -392,7 +392,7 @@ CODESTARTobjQueryInterface(expr)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJexpr;
+	//xxxpIf->oID = OBJexpr;
 
 	pIf->Construct = exprConstruct;
 	pIf->ConstructFinalize = exprConstructFinalize;
@@ -408,10 +408,10 @@ ENDobjQueryInterface(expr)
  */
 BEGINObjClassInit(expr, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(vmprg));
-	CHKiRet(objUse(var));
-	CHKiRet(objUse(ctok_token));
-	CHKiRet(objUse(ctok));
+	CHKiRet(objUse(vmprg, CORE_COMPONENT));
+	CHKiRet(objUse(var, CORE_COMPONENT));
+	CHKiRet(objUse(ctok_token, CORE_COMPONENT));
+	CHKiRet(objUse(ctok, CORE_COMPONENT));
 
 	OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, exprConstructFinalize);
 ENDObjClassInit(expr)
diff --git a/msg.c b/msg.c
index 029dc70c..7fa8234c 100644
--- a/msg.c
+++ b/msg.c
@@ -2196,13 +2196,16 @@ MsgGetSeverity(obj_t *pThis, int *piSeverity)
 }
 
 
+/* dummy */
+rsRetVal msgQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
+
 /* Initialize the message class. Must be called as the very first method
  * before anything else is called inside this class.
  * rgerhards, 2008-01-04
  */
 BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE)
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	/* set our own handlers */
 	OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize);
diff --git a/obj-types.h b/obj-types.h
index 23c2d761..ad8c555c 100644
--- a/obj-types.h
+++ b/obj-types.h
@@ -43,30 +43,10 @@ typedef enum {
 	PROPTYPE_SYSLOGTIME = 7
 } propType_t;
 
-
-/* object Types/IDs */
-typedef enum {	/* IDs of known object "types/classes" */
-	OBJNull = 0,	/* no valid object (we do not start at zero so we can detect calloc()) */
-	OBJmsg = 1,
-	OBJstrm = 2,
-	OBJwtp = 3,
-	OBJwti = 4,
-	OBJqueue = 5,
-	OBJctok = 6,
-	OBJctok_token = 7,
-	OBJvar = 8,
-	OBJvmop = 9,
-	OBJvmprg = 10,
-	OBJvm = 11,
-	OBJsysvar = 12,
-	OBJvmstk = 13,
-	OBJobj = 14,	/* the base object itself - somewhat tricky, but required... */
-	OBJexpr = 15	/* remeber to UPDATE OBJ_NUM_IDS (below) if you add one! */
-} objID_t;	
-#define OBJ_NUM_IDS 16
+typedef unsigned objID_t;
 
 typedef enum {	/* IDs of base methods supported by all objects - used for jump table, so
-		 * they must start at zero and be incremented. -- rgerahrds, 2008-01-04
+		 * they must start at zero and be incremented. -- rgerhards, 2008-01-04
 		 */
 	objMethod_CONSTRUCT = 0,
 	objMethod_DESTRUCT = 1,
@@ -79,11 +59,25 @@ typedef enum {	/* IDs of base methods supported by all objects - used for jump t
 } objMethod_t;
 #define OBJ_NUM_METHODS 8	/* must be updated to contain the max number of methods supported */
 
+
+/* the base data type for interfaces
+ * This MUST be in sync with the ifBEGIN macro
+ */
+typedef struct interface_s {
+	int ifVersion;	/* must be set to version requested */ 
+	//xxxobjID_t oID;	/* our object ID (later dynamically assigned) */
+} interface_t;
+
+
 typedef struct objInfo_s {
-	objID_t	objID;	
+objID_t	objID;	
+	uchar *pszID; /* the object ID as a string */
+	size_t lenID; /* length of the ID string */
 	int iObjVers;
 	uchar *pszName;
 	rsRetVal (*objMethods[OBJ_NUM_METHODS])();
+	// TODO: the queryInterface pointer should probably be added here
+	rsRetVal (*QueryIF)(interface_t*);
 } objInfo_t;
 
 
@@ -100,6 +94,7 @@ typedef struct obj {	/* the dummy struct that each derived class can be casted t
  * other objects.
  */
 #ifndef NDEBUG /* this means if debug... */
+#include <string.h>
 #	define BEGINobjInstance \
 		obj_t objData
 #	define ISOBJ_assert(pObj) \
@@ -111,7 +106,7 @@ typedef struct obj {	/* the dummy struct that each derived class can be casted t
 		do { \
 		ASSERT(pObj != NULL); \
 		ASSERT((unsigned) ((obj_t*) (pObj))->iObjCooCKiE == (unsigned) 0xBADEFEE); \
-		ASSERT(objGetObjID(pObj) == OBJ##objType); \
+		ASSERT(!strcmp((char*)(((obj_t*)pObj)->pObjInfo->pszID), #objType)); \
 		} while(0);
 #else /* non-debug mode, no checks but much faster */
 #	define BEGINobjInstance obj_t objData
@@ -170,11 +165,12 @@ rsRetVal objName##ClassInit(void) \
 	if(objType == OBJ_IS_CORE_MODULE) { \
 		CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ \
 	} \
-	CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, OBJ##objName, (uchar*) #objName, objVers, \
-	                         (rsRetVal (*)(void*))objName##Construct,  (rsRetVal (*)(void*))objName##Destruct)); 
+	CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, (uchar*) #objName, objVers, \
+	                         (rsRetVal (*)(void*))objName##Construct,  (rsRetVal (*)(void*))objName##Destruct,\
+				 (rsRetVal (*)(interface_t*))objName##QueryInterface)); 
 
 #define ENDObjClassInit(objName) \
-	obj.RegisterObj(OBJ##objName, pObjInfoOBJ); \
+	iRet = obj.RegisterObj((uchar*)#objName, pObjInfoOBJ); \
 finalize_it: \
 	RETiRet; \
 }
@@ -302,7 +298,7 @@ finalize_it: \
 /* this defines the QueryInterface print entry point. Over time, it should be
  * present in all objects.
  */
-#define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pThis)
+//#define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pThis)
 #define BEGINobjQueryInterface(obj) \
 	rsRetVal obj##QueryInterface(obj##_if_t *pIf) \
 	{ \
@@ -315,14 +311,6 @@ finalize_it: \
 		RETiRet; \
 	} 
 
-/* the base data type for interfaces
- * This MUST be in sync with the ifBEGIN macro
- */
-typedef struct interface_s {
-	int ifVersion;	/* must be set to version requested */ 
-	objID_t oID;	/* our object ID (later dynamically assigned) */
-} interface_t;
-
 
 /* the following macros should be used to define interfaces inside the
  * header files.
@@ -337,8 +325,9 @@ typedef struct interface_s {
  * just the class itself!). It must be called before any of the object's
  * methods can be accessed.
  */
-#define objUse(obj) \
-	obj##QueryInterface(&obj)
+#define CORE_COMPONENT NULL /* use this to indicate this is a core component */
+#define objUse(objName, FILENAME) \
+	obj.UseObj((uchar*)#objName, (uchar*)FILENAME, (void*) &objName)
 
 /* defines data that must always be present at the very begin of the interface structure */
 #define ifBEGIN \
@@ -357,7 +346,7 @@ typedef struct interface_s {
  */
 #define PROTOTYPEObj(obj) \
 	PROTOTYPEObjClassInit(obj); \
-	PROTOTYPEObjQueryInterface(obj) \
+	//PROTOTYPEObjQueryInterface(obj)
 /* ------------------------------ end object loader system ------------------------------ */
 
 
diff --git a/obj.c b/obj.c
index 01694d41..cd28a3e2 100644
--- a/obj.c
+++ b/obj.c
@@ -39,6 +39,13 @@
  * I agree, technically this is much the same, but from an architecture
  * point of view it looks cleaner (at least to me).
  * 
+ * Please note that there is another egg-hen problem: we use a linked list,
+ * which is provided by the linkedList object. However, we need to
+ * initialize the linked list before we can provide the UseObj()
+ * functionality. That, in turn, would probably be required by the 
+ * linkedList object. So the solution is to use a backdoor just to
+ * init the linked list and from then on use the usual interfaces.
+ *
  * File begun on 2008-01-04 by RGerhards
  *
  * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
@@ -68,6 +75,9 @@
 #include <ctype.h>
 #include <assert.h>
 
+/* how many objects are supported by rsyslogd? */
+#define OBJ_NUM_IDS 100 //TODO 16 were currently in use 2008-02-29
+
 #include "rsyslog.h"
 #include "syslogd-types.h"
 #include "srUtils.h"
@@ -75,10 +85,10 @@
 #include "stream.h"
 
 /* static data */
+DEFobjCurrIf(obj) /* we define our own interface, as this is expected by some macros! */
 DEFobjCurrIf(var)
 static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information pointers */
 
-/* some defines */
 
 /* cookies for serialized lines */
 #define COOKIE_OBJLINE   '<'
@@ -86,6 +96,9 @@ static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information poin
 #define COOKIE_ENDLINE   '>'
 #define COOKIE_BLANKLINE '.'
 
+/* forward definitions */
+static rsRetVal FindObjInfo(cstr_t *pszObjName, objInfo_t **ppInfo);
+
 /* methods */
 
 /* This is a dummy method to be used when a standard method has not been
@@ -108,11 +121,12 @@ static rsRetVal objInfoNotImplementedDummy(void __attribute__((unused)) *pThis)
  * resulting object shall be cached during the lifetime of the class and each
  * object shall receive a reference. A constructor and destructor MUST be provided for all
  * objects, thus they are in the parameter list.
- * pszName must point to constant pool memory. It is never freed.
+ * pszID is the identifying object name and must point to constant pool memory. It is never freed.
  */
 static rsRetVal
-InfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers,
-                 rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *))
+InfoConstruct(objInfo_t **ppThis, uchar *pszID, int iObjVers,
+              rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *),
+	      rsRetVal (*pQueryIF)(interface_t*))
 {
 	DEFiRet;
 	int i;
@@ -124,9 +138,12 @@ InfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers,
 	if((pThis = calloc(1, sizeof(objInfo_t))) == NULL)
 		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
 
-	pThis->pszName = pszName;
+	pThis->pszID = pszID;
+	pThis->lenID = strlen((char*)pszID);
+	pThis->pszName = (uchar*)strdup((char*)pszID); /* it's OK if we have NULL ptr, GetName() will deal with that! */
 	pThis->iObjVers = iObjVers;
-	pThis->objID = objID;
+	pThis->QueryIF = pQueryIF;
+	//xxxpThis->objID = objID;
 
 	pThis->objMethods[0] = pConstruct;
 	pThis->objMethods[1] = pDestruct;
@@ -190,16 +207,10 @@ static rsRetVal objSerializeHeader(strm_t *pStrm, obj_t *pObj, uchar *pszRecType
 
 	/* object type, version and string length */
 	CHKiRet(strmWriteChar(pStrm, ':'));
-	CHKiRet(strmWriteLong(pStrm, objGetObjID(pObj)));
+	CHKiRet(strmWrite(pStrm, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID));
 	CHKiRet(strmWriteChar(pStrm, ':'));
 	CHKiRet(strmWriteLong(pStrm, objGetVersion(pObj)));
 
-	/* and finally we write the object name - this is primarily meant for
-	 * human readers. The idea is that it can be easily skipped when reading
-	 * the object back in
-	 */
-	CHKiRet(strmWriteChar(pStrm, ':'));
-	CHKiRet(strmWrite(pStrm, objGetClassName(pObj), strlen((char*)objGetClassName(pObj))));
 	/* record trailer */
 	CHKiRet(strmWriteChar(pStrm, ':'));
 	CHKiRet(strmWriteChar(pStrm, '\n'));
@@ -386,6 +397,40 @@ finalize_it:
 /* define a helper to make code below a bit cleaner (and quicker to write) */
 #define NEXTC CHKiRet(strmReadChar(pStrm, &c))//;dbgprintf("c: %c\n", c);
 
+
+/* de-serialize an embedded, non-octect-counted string. This is useful
+ * for deserializing the object name inside the header. The string is
+ * terminated by the first occurence of the ':' character.
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+objDeserializeEmbedStr(cstr_t **ppStr, strm_t *pStrm)
+{
+	DEFiRet;
+	uchar c;
+	cstr_t *pStr = NULL;
+
+	assert(ppStr != NULL);
+
+	CHKiRet(rsCStrConstruct(&pStr));
+
+	NEXTC;
+	while(c != ':') {
+		CHKiRet(rsCStrAppendChar(pStr, c));
+		NEXTC;
+	}
+	CHKiRet(rsCStrFinish(pStr));
+
+	*ppStr = pStr;
+
+finalize_it:
+	if(iRet != RS_RET_OK && pStr != NULL)
+		rsCStrDestruct(&pStr);
+
+	RETiRet;
+}
+
+
 /* de-serialize a number */
 static rsRetVal objDeserializeNumber(number_t *pNum, strm_t *pStrm)
 {
@@ -492,14 +537,13 @@ finalize_it:
 /* de-serialize an object header
  * rgerhards, 2008-01-07
  */
-static rsRetVal objDeserializeHeader(uchar *pszRecType, objID_t *poID, int* poVers, strm_t *pStrm)
+static rsRetVal objDeserializeHeader(uchar *pszRecType, cstr_t **ppstrID, int* poVers, strm_t *pStrm)
 {
 	DEFiRet;
-	number_t ioID;
 	number_t oVers;
 	uchar c;
 
-	assert(poID != NULL);
+	assert(ppstrID != NULL);
 	assert(poVers != NULL);
 	assert(!strcmp((char*) pszRecType, "Obj") || !strcmp((char*) pszRecType, "OPB"));
 
@@ -513,19 +557,15 @@ static rsRetVal objDeserializeHeader(uchar *pszRecType, objID_t *poID, int* poVe
 	NEXTC; if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS);
 
 	/* object type and version */
-	CHKiRet(objDeserializeNumber(&ioID, pStrm));
+	CHKiRet(objDeserializeEmbedStr(ppstrID, pStrm));
 	CHKiRet(objDeserializeNumber(&oVers, pStrm));
 
-	if(ioID < 1 || ioID >= OBJ_NUM_IDS)
-		ABORT_FINALIZE(RS_RET_INVALID_OID);
-
 	/* and now we skip over the rest until the delemiting \n */
 	NEXTC;
 	while(c != '\n') {
 		NEXTC;
 	}
 
-	*poID = (objID_t) ioID;
 	*poVers = oVers;
 
 finalize_it:
@@ -662,21 +702,21 @@ finalize_it:
  * of the trailer. Header must already have been processed.
  * rgerhards, 2008-01-11
  */
-static rsRetVal objDeserializeProperties(obj_t *pObj, objID_t oID, strm_t *pStrm)
+static rsRetVal objDeserializeProperties(obj_t *pObj, objInfo_t *pObjInfo, strm_t *pStrm)
 {
 	DEFiRet;
 	var_t *pVar;
 
 	ISOBJ_assert(pObj);
 	ISOBJ_TYPE_assert(pStrm, strm);
-	ASSERT(oID > 0 && oID < OBJ_NUM_IDS);
+	ASSERT(pObjInfo != NULL);
 
 	CHKiRet(var.Construct(&pVar));
 	CHKiRet(var.ConstructFinalize(pVar));
 
 	iRet = objDeserializeProperty(pVar, pStrm);
 	while(iRet == RS_RET_OK) {
-		CHKiRet(arrObjInfo[oID]->objMethods[objMethod_SETPROPERTY](pObj, pVar));
+		CHKiRet(pObjInfo->objMethods[objMethod_SETPROPERTY](pObj, pVar));
 		iRet = objDeserializeProperty(pVar, pStrm);
 	}
 	var.Destruct(&pVar);
@@ -699,16 +739,17 @@ finalize_it:
  * rgerhards, 2008-01-07
  */
 static rsRetVal
-Deserialize(void *ppObj, objID_t objTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr)
+Deserialize(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr)
 {
 	DEFiRet;
 	rsRetVal iRetLocal;
 	obj_t *pObj = NULL;
-	objID_t oID = 0; /* this assignment is just to supress a compiler warning - this saddens me */
 	int oVers = 0;   /* after all, it is totally useless but takes up some execution time...    */
+	cstr_t *pstrID = NULL;
+	objInfo_t *pObjInfo;
 
 	assert(ppObj != NULL);
-	assert(objTypeExpected > 0 && objTypeExpected < OBJ_NUM_IDS);
+	assert(pszTypeExpected != NULL);
 	ISOBJ_TYPE_assert(pStrm, strm);
 
 	/* we de-serialize the header. if all goes well, we are happy. However, if
@@ -719,20 +760,22 @@ Deserialize(void *ppObj, objID_t objTypeExpected, strm_t *pStrm, rsRetVal (*fFix
 	 * rgerhards, 2008-07-08
 	 */
 	do {
-		iRetLocal = objDeserializeHeader((uchar*) "Obj", &oID, &oVers, pStrm);
+		iRetLocal = objDeserializeHeader((uchar*) "Obj", &pstrID, &oVers, pStrm);
 		if(iRetLocal != RS_RET_OK) {
 			dbgprintf("objDeserialize error %d during header processing - trying to recover\n", iRetLocal);
-abort();
 			CHKiRet(objDeserializeTryRecover(pStrm));
 		}
 	} while(iRetLocal != RS_RET_OK);
 
-	if(oID != objTypeExpected)
+	if(rsCStrSzStrCmp(pstrID, pszTypeExpected, strlen((char*)pszTypeExpected))) // TODO: optimize strlen() - caller shall provide
 		ABORT_FINALIZE(RS_RET_INVALID_OID);
-	CHKiRet(arrObjInfo[oID]->objMethods[objMethod_CONSTRUCT](&pObj));
+
+	CHKiRet(FindObjInfo(pstrID, &pObjInfo));
+
+	CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCT](&pObj));
 
 	/* we got the object, now we need to fill the properties */
-	CHKiRet(objDeserializeProperties(pObj, oID, pStrm));
+	CHKiRet(objDeserializeProperties(pObj, pObjInfo, pStrm));
 
 	/* check if we need to call a fixup function that modifies the object
 	 * before it is finalized. -- rgerhards, 2008-01-13
@@ -741,8 +784,8 @@ abort();
 		CHKiRet(fFixup(pObj, pUsr));
 
 	/* we have a valid object, let's finalize our work and return */
-	if(objInfoIsImplemented(arrObjInfo[oID], objMethod_CONSTRUCTION_FINALIZER))
-		CHKiRet(arrObjInfo[oID]->objMethods[objMethod_CONSTRUCTION_FINALIZER](pObj));
+	if(objInfoIsImplemented(pObjInfo, objMethod_CONSTRUCTION_FINALIZER))
+		CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCTION_FINALIZER](pObj));
 
 	*((obj_t**) ppObj) = pObj;
 
@@ -750,6 +793,9 @@ finalize_it:
 	if(iRet != RS_RET_OK && pObj != NULL)
 		free(pObj); // TODO: check if we can call destructor 2008-01-13 rger
 
+	if(pstrID != NULL)
+		rsCStrDestruct(&pstrID);
+
 	RETiRet;
 }
 
@@ -762,8 +808,9 @@ objDeserializeObjAsPropBag(obj_t *pObj, strm_t *pStrm)
 {
 	DEFiRet;
 	rsRetVal iRetLocal;
-	objID_t oID = 0; /* this assignment is just to supress a compiler warning - this saddens me */
+	cstr_t *pstrID = NULL;
 	int oVers = 0;   /* after all, it is totally useless but takes up some execution time...    */
+	objInfo_t *pObjInfo;
 
 	ISOBJ_assert(pObj);
 	ISOBJ_TYPE_assert(pStrm, strm);
@@ -776,20 +823,25 @@ objDeserializeObjAsPropBag(obj_t *pObj, strm_t *pStrm)
 	 * rgerhards, 2008-07-08
 	 */
 	do {
-		iRetLocal = objDeserializeHeader((uchar*) "Obj", &oID, &oVers, pStrm);
+		iRetLocal = objDeserializeHeader((uchar*) "Obj", &pstrID, &oVers, pStrm);
 		if(iRetLocal != RS_RET_OK) {
 			dbgprintf("objDeserializeObjAsPropBag error %d during header - trying to recover\n", iRetLocal);
 			CHKiRet(objDeserializeTryRecover(pStrm));
 		}
 	} while(iRetLocal != RS_RET_OK);
 
-	if(oID != objGetObjID(pObj))
+	if(rsCStrSzStrCmp(pstrID, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID))
 		ABORT_FINALIZE(RS_RET_INVALID_OID);
 
+	CHKiRet(FindObjInfo(pstrID, &pObjInfo));
+
 	/* we got the object, now we need to fill the properties */
-	CHKiRet(objDeserializeProperties(pObj, oID, pStrm));
+	CHKiRet(objDeserializeProperties(pObj, pObjInfo, pStrm));
 
 finalize_it:
+	if(pstrID != NULL)
+		rsCStrDestruct(&pstrID);
+
 	RETiRet;
 }
 
@@ -808,8 +860,9 @@ DeserializePropBag(obj_t *pObj, strm_t *pStrm)
 {
 	DEFiRet;
 	rsRetVal iRetLocal;
-	objID_t oID = 0; /* this assignment is just to supress a compiler warning - this saddens me */
-	int oVers = 0;   /* after all, it is totally useless but takes up some execution time...    */
+	cstr_t *pstrID = NULL;
+	int oVers;
+	objInfo_t *pObjInfo;
 
 	ISOBJ_assert(pObj);
 	ISOBJ_TYPE_assert(pStrm, strm);
@@ -822,20 +875,25 @@ DeserializePropBag(obj_t *pObj, strm_t *pStrm)
 	 * rgerhards, 2008-07-08
 	 */
 	do {
-		iRetLocal = objDeserializeHeader((uchar*) "OPB", &oID, &oVers, pStrm);
+		iRetLocal = objDeserializeHeader((uchar*) "OPB", &pstrID, &oVers, pStrm);
 		if(iRetLocal != RS_RET_OK) {
 			dbgprintf("objDeserializePropBag error %d during header - trying to recover\n", iRetLocal);
 			CHKiRet(objDeserializeTryRecover(pStrm));
 		}
 	} while(iRetLocal != RS_RET_OK);
 
-	if(oID != objGetObjID(pObj))
+	if(rsCStrSzStrCmp(pstrID, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID))
 		ABORT_FINALIZE(RS_RET_INVALID_OID);
 
+	CHKiRet(FindObjInfo(pstrID, &pObjInfo));
+
 	/* we got the object, now we need to fill the properties */
-	CHKiRet(objDeserializeProperties(pObj, oID, pStrm));
+	CHKiRet(objDeserializeProperties(pObj, pObjInfo, pStrm));
 
 finalize_it:
+	if(pstrID != NULL)
+		rsCStrDestruct(&pstrID);
+
 	RETiRet;
 }
 
@@ -902,27 +960,116 @@ GetName(obj_t *pThis)
 }
 
 
-/* register a classe's info pointer, so that we can reference it later, if needed to
+/* Find the objInfo object for the current object
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+FindObjInfo(cstr_t *pstrOID, objInfo_t **ppInfo)
+{
+	DEFiRet;
+	int bFound;
+	int i;
+
+	assert(pstrOID != NULL);
+	assert(ppInfo != NULL);
+
+	bFound = 0;
+	i = 0;
+	while(!bFound && i < OBJ_NUM_IDS && arrObjInfo[i] != NULL) {
+		if(!rsCStrSzStrCmp(pstrOID, arrObjInfo[i]->pszID, arrObjInfo[i]->lenID)) {
+			bFound = 1;
+			break;
+		}
+		++i;
+	}
+
+	if(!bFound)
+		ABORT_FINALIZE(RS_RET_NOT_FOUND);
+
+	*ppInfo = arrObjInfo[i];
+
+finalize_it:
+	if(iRet == RS_RET_OK) {
+		dbgprintf("caller requested object '%s', found at index %d\n", (*ppInfo)->pszID, i);
+	} else {
+		dbgprintf("caller requested object '%s', not found (iRet %d)\n", rsCStrGetSzStr(pstrOID), iRet);
+	}
+
+	RETiRet;
+}
+
+
+/* register a classes' info pointer, so that we can reference it later, if needed to
  * (e.g. for de-serialization support).
  * rgerhards, 2008-01-07
+ * In this function, we look for a free space in the object table. While we do so, we
+ * also detect if the same object has already been registered, which is not valid.
+ * rgerhards, 2008-02-29
  */
 static rsRetVal
-RegisterObj(objID_t oID, objInfo_t *pInfo)
+RegisterObj(uchar *pszObjName, objInfo_t *pInfo)
 {
 	DEFiRet;
+	int bFound;
+	int i;
 
+	assert(pszObjName != NULL);
 	assert(pInfo != NULL);
-	assert(arrObjInfo[oID] == NULL);
-	if(oID < 1 || oID > OBJ_NUM_IDS)
-		ABORT_FINALIZE(RS_RET_INVALID_OID);
 
-	arrObjInfo[oID] = pInfo;
+	bFound = 0;
+	i = 0;
+	while(!bFound && i < OBJ_NUM_IDS && arrObjInfo[i] != NULL) {
+		if(   arrObjInfo[i] != NULL
+		   && !strcmp((char*)arrObjInfo[i]->pszID, (char*)pszObjName)) {
+			bFound = 1;
+			break;
+		}
+		++i;
+	}
+
+	if(bFound)           ABORT_FINALIZE(RS_RET_OBJ_ALREADY_REGISTERED);
+	if(i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE);
+
+	arrObjInfo[i] = pInfo;
+	dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF);
 
 finalize_it:
 	RETiRet;
 }
 
 
+/* This function shall be called by anyone who would like to use an object. It will
+ * try to locate the object, load it into memory if not already present and return
+ * a pointer to the objects interface.
+ * rgerhards, 2008-02-29
+ */
+static rsRetVal
+UseObj(uchar *pObjName, uchar *pObjFile, interface_t **ppIf)
+{
+	DEFiRet;
+	cstr_t *pStr = NULL;
+	objInfo_t *pObjInfo;
+
+	CHKiRet(rsCStrConstructFromszStr(&pStr, pObjName));
+	iRet =FindObjInfo(pStr, &pObjInfo);
+
+	if(iRet == RS_RET_NOT_FOUND) {
+		/* in this case, we need to see if we can dynamically load the object */
+		FINALIZE; /* TODO: implement */
+	} else if(iRet != RS_RET_OK) {
+		FINALIZE; /* give up */
+	}
+
+	pObjInfo->QueryIF(ppIf);
+
+finalize_it:
+	if(pStr != NULL)
+		rsCStrDestruct(&pStr);
+
+	RETiRet;
+}
+
+
 /* queryInterface function
  * rgerhards, 2008-02-29
  */
@@ -937,8 +1084,9 @@ CODESTARTobjQueryInterface(obj)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJobj;
+	//xxxpIf->oID = OBJobj;
 
+	pIf->UseObj = UseObj;
 	pIf->InfoConstruct = InfoConstruct;
 	pIf->DestructObjSelf = DestructObjSelf;
 	pIf->BeginSerializePropBag = BeginSerializePropBag;
@@ -987,12 +1135,13 @@ objClassInit(void)
 	}
 
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objGetObjInterface(&obj)); /* get ourselves ;) */
+CHKiRet(varClassInit());
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 finalize_it:
 	RETiRet;
 }
 
-/*
- * vi:set ai:
+/* vi:set ai:
  */
diff --git a/obj.h b/obj.h
index cf5aed6a..4cce9d02 100644
--- a/obj.h
+++ b/obj.h
@@ -71,8 +71,7 @@
 	DEFobjCurrIf(obj)
 
 
-#define objGetClassName(pThis) (((obj_t*) (pThis))->pObjInfo->pszName)
-#define objGetObjID(pThis) (((obj_t*) (pThis))->pObjInfo->objID)
+#define objGetClassName(pThis) (((obj_t*) (pThis))->pObjInfo->pszID)
 #define objGetVersion(pThis) (((obj_t*) (pThis))->pObjInfo->iObjVers)
 /* the next macro MUST be called in Constructors: */
 #ifndef NDEBUG /* this means if debug... */
@@ -94,16 +93,17 @@
 /* interfaces */
 BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */
 	rsRetVal (*UseObj)(uchar *pObjName, uchar *pObjFile, interface_t **ppIf);
-	rsRetVal (*InfoConstruct)(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers,
-		                  rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *));
+	rsRetVal (*InfoConstruct)(objInfo_t **ppThis, uchar *pszID, int iObjVers,
+		                  rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *),
+	      			  rsRetVal (*pQueryIF)(interface_t*));
 	rsRetVal (*DestructObjSelf)(obj_t *pThis);
 	rsRetVal (*BeginSerializePropBag)(strm_t *pStrm, obj_t *pObj);
 	rsRetVal (*InfoSetMethod)(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void*));
 	rsRetVal (*BeginSerialize)(strm_t *pStrm, obj_t *pObj);
 	rsRetVal (*SerializeProp)(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr);
 	rsRetVal (*EndSerialize)(strm_t *pStrm);
-	rsRetVal (*RegisterObj)(objID_t oID, objInfo_t *pInfo);
-	rsRetVal (*Deserialize)(void *ppObj, objID_t objTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr);
+	rsRetVal (*RegisterObj)(uchar *pszObjName, objInfo_t *pInfo);
+	rsRetVal (*Deserialize)(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr);
 	rsRetVal (*DeserializePropBag)(obj_t *pObj, strm_t *pStrm);
 	rsRetVal (*SetName)(obj_t *pThis, uchar *pszName);
 	uchar *  (*GetName)(obj_t *pThis);
diff --git a/queue.c b/queue.c
index a6bcff9f..58b4d618 100644
--- a/queue.c
+++ b/queue.c
@@ -728,15 +728,15 @@ queueTryLoadPersistedInfo(queue_t *pThis)
 
 	while(iUngottenObjs > 0) {
 		/* fill the queue from disk */
-		CHKiRet(obj.Deserialize((void*) &pUsr, OBJmsg, psQIF, NULL, NULL));
+		CHKiRet(obj.Deserialize((void*) &pUsr, (uchar*)"msg", psQIF, NULL, NULL));
 		queueUngetObj(pThis, pUsr, MUTEX_ALREADY_LOCKED);
 		--iUngottenObjs; /* one less */
 	}
 
 	/* and now the stream objects (some order as when persisted!) */
-	CHKiRet(obj.Deserialize(&pThis->tVars.disk.pWrite, OBJstrm, psQIF,
+	CHKiRet(obj.Deserialize(&pThis->tVars.disk.pWrite, (uchar*) "strm", psQIF,
 			       (rsRetVal(*)(obj_t*,void*))queueLoadPersStrmInfoFixup, pThis));
-	CHKiRet(obj.Deserialize(&pThis->tVars.disk.pRead, OBJstrm, psQIF,
+	CHKiRet(obj.Deserialize(&pThis->tVars.disk.pRead, (uchar*) "strm", psQIF,
 			       (rsRetVal(*)(obj_t*,void*))queueLoadPersStrmInfoFixup, pThis));
 
 	CHKiRet(strmSeekCurrOffs(pThis->tVars.disk.pWrite));
@@ -861,7 +861,7 @@ static rsRetVal qDelDisk(queue_t *pThis, void **ppUsr)
 	int64 offsOut;
 
 	CHKiRet(strmGetCurrOffset(pThis->tVars.disk.pRead, &offsIn));
-	CHKiRet(obj.Deserialize(ppUsr, OBJmsg, pThis->tVars.disk.pRead, NULL, NULL));
+	CHKiRet(obj.Deserialize(ppUsr, (uchar*) "msg", pThis->tVars.disk.pRead, NULL, NULL));
 	CHKiRet(strmGetCurrOffset(pThis->tVars.disk.pRead, &offsOut));
 
 	/* This time it is a bit tricky: we free disk space only upon file deletion. So we need
@@ -2106,6 +2106,10 @@ finalize_it:
 	RETiRet;
 }
 #undef	isProp
+
+/* dummy */
+rsRetVal queueQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
+
 /* Initialize the stream class. Must be called as the very first method
  * before anything else is called inside this class.
  * rgerhards, 2008-01-09
diff --git a/rsyslog.h b/rsyslog.h
index c44e73cc..5f8a22a1 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -135,6 +135,8 @@ enum rsRetVal_				/** return value. All methods return this if not specified oth
 	RS_RET_INVALID_VAR = -2058, /**< a var_t or its content is unsuitable, eg. VARTYPE_NONE */
 	RS_RET_INVALID_NUMBER = -2059, /**< number invalid during parsing */
 	RS_RET_NOT_A_NUMBER = -2060, /**< e.g. conversion impossible because the string is not a number */
+	RS_RET_OBJ_ALREADY_REGISTERED = -2061, /**< object (name) is already registered */
+	RS_RET_OBJ_REGISTRY_OUT_OF_SPACE = -2062, /**< the object registry has run out of space */
 
 	/* RainerScript error messages (range 1000.. 1999) */
 	RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/stream.c b/stream.c
index 35b38c5e..bc345f93 100644
--- a/stream.c
+++ b/stream.c
@@ -884,6 +884,26 @@ strmGetCurrOffset(strm_t *pThis, int64 *pOffs)
 }
 
 
+/* queryInterface function
+ * rgerhards, 2008-02-29
+ */
+BEGINobjQueryInterface(strm)
+CODESTARTobjQueryInterface(strm)
+	if(pIf->ifVersion != strmCURR_IF_VERSION) { /* check for current version, increment on each change */
+		ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+	}
+
+	/* ok, we have the right interface, so let's fill it
+	 * Please note that we may also do some backwards-compatibility
+	 * work here (if we can support an older interface version - that,
+	 * of course, also affects the "if" above).
+	 */
+	//xxxpIf->oID = OBJvm;
+
+finalize_it:
+ENDobjQueryInterface(strm)
+
+
 /* Initialize the stream class. Must be called as the very first method
  * before anything else is called inside this class.
  * rgerhards, 2008-01-09
diff --git a/stream.h b/stream.h
index 903bb284..0dc5e646 100644
--- a/stream.h
+++ b/stream.h
@@ -90,6 +90,12 @@ typedef struct strm_s {
 	int bInRecord;	/* if 1, indicates that we are currently writing a not-yet complete record */
 } strm_t;
 
+/* interfaces */
+BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */
+ENDinterface(strm)
+#define strmCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+
+
 /* prototypes */
 rsRetVal strmConstruct(strm_t **ppThis);
 rsRetVal strmConstructFinalize(strm_t __attribute__((unused)) *pThis);
diff --git a/syslogd.c b/syslogd.c
index 2f7ba0f2..cf2b85e7 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -3576,9 +3576,6 @@ static rsRetVal InitGlobalClasses(void)
 	DEFiRet;
 
 	CHKiRet(objClassInit()); /* *THIS* *MUST* always be the first class initilizer being called! */
-	/* dummy "classes" */
-	CHKiRet(confClassInit());
-	CHKiRet(actionClassInit());
 
 	/* real ones */
 	CHKiRet(msgClassInit());
@@ -3587,19 +3584,23 @@ static rsRetVal InitGlobalClasses(void)
 	CHKiRet(wtpClassInit());
 	CHKiRet(queueClassInit());
 	CHKiRet(vmstkClassInit());
+	//TODO: currently done in objClassInit CHKiRet(varClassInit());
+	CHKiRet(sysvarClassInit());
 	CHKiRet(vmClassInit());
 	CHKiRet(vmopClassInit());
 	CHKiRet(vmprgClassInit());
-	CHKiRet(sysvarClassInit());
-	CHKiRet(varClassInit());
 	CHKiRet(ctok_tokenClassInit());
 	CHKiRet(ctokClassInit());
 	CHKiRet(exprClassInit());
 
+	/* dummy "classes" */
+	CHKiRet(confClassInit());
+	CHKiRet(actionClassInit());
+
 	/* request objects we use */
 	CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
-	CHKiRet(objUse(expr));
-	CHKiRet(objUse(vm));
+	CHKiRet(obj.UseObj((uchar*)"expr", NULL, (void*) &expr));
+	CHKiRet(obj.UseObj((uchar*)"vm", NULL, (void*) &vm));
 
 finalize_it:
 	RETiRet;
diff --git a/sysvar.c b/sysvar.c
index aafcb688..6fb2aab3 100644
--- a/sysvar.c
+++ b/sysvar.c
@@ -172,7 +172,7 @@ CODESTARTobjQueryInterface(sysvar)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJsysvar;
+	//xxxpIf->oID = "sysvar";//OBJsysvar;
 
 	pIf->Construct = sysvarConstruct;
 	pIf->ConstructFinalize = sysvarConstructFinalize;
@@ -188,7 +188,7 @@ ENDobjQueryInterface(sysvar)
  */
 BEGINObjClassInit(sysvar, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	/* set our own handlers */
 	OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, sysvarConstructFinalize);
diff --git a/var.c b/var.c
index aa2100b4..c1d66643 100644
--- a/var.c
+++ b/var.c
@@ -366,7 +366,7 @@ CODESTARTobjQueryInterface(var)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJvar;
+	//xxxpIf->oID = OBJvar;
 
 	pIf->Construct = varConstruct;
 	pIf->ConstructFinalize = varConstructFinalize;
diff --git a/vm.c b/vm.c
index 5c0eccba..37048a9b 100644
--- a/vm.c
+++ b/vm.c
@@ -504,7 +504,7 @@ CODESTARTobjQueryInterface(vm)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJvm;
+	//xxxpIf->oID = OBJvm;
 
 	pIf->Construct = vmConstruct;
 	pIf->ConstructFinalize = vmConstructFinalize;
@@ -524,9 +524,9 @@ ENDobjQueryInterface(vm)
  */
 BEGINObjClassInit(vm, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(vmstk));
-	CHKiRet(objUse(var));
-	CHKiRet(objUse(sysvar));
+	CHKiRet(objUse(vmstk, CORE_COMPONENT));
+	CHKiRet(objUse(var, CORE_COMPONENT));
+	CHKiRet(objUse(sysvar, CORE_COMPONENT));
 
 	/* set our own handlers */
 	OBJSetMethodHandler(objMethod_DEBUGPRINT, vmDebugPrint);
diff --git a/vmop.c b/vmop.c
index 199ec4cd..affa83e7 100644
--- a/vmop.c
+++ b/vmop.c
@@ -199,7 +199,7 @@ CODESTARTobjQueryInterface(vmop)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJvmop;
+	//xxxpIf->oID = OBJvmop;
 
 	pIf->Construct = vmopConstruct;
 	pIf->ConstructFinalize = vmopConstructFinalize;
@@ -218,7 +218,7 @@ ENDobjQueryInterface(vmop)
  */
 BEGINObjClassInit(vmop, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	OBJSetMethodHandler(objMethod_DEBUGPRINT, vmopDebugPrint);
 	OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmopConstructFinalize);
diff --git a/vmprg.c b/vmprg.c
index dde899ad..a1b41ad8 100644
--- a/vmprg.c
+++ b/vmprg.c
@@ -145,7 +145,7 @@ CODESTARTobjQueryInterface(vmprg)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJvmprg;
+	//xxxpIf->oID = OBJvmprg;
 
 	pIf->Construct = vmprgConstruct;
 	pIf->ConstructFinalize = vmprgConstructFinalize;
@@ -163,7 +163,7 @@ ENDobjQueryInterface(vmprg)
  */
 BEGINObjClassInit(vmprg, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(vmop));
+	CHKiRet(objUse(vmop, CORE_COMPONENT));
 
 	/* set our own handlers */
 	OBJSetMethodHandler(objMethod_DEBUGPRINT, vmprgDebugPrint);
diff --git a/vmstk.c b/vmstk.c
index 3f07a8f4..9ca815ff 100644
--- a/vmstk.c
+++ b/vmstk.c
@@ -201,7 +201,7 @@ CODESTARTobjQueryInterface(vmstk)
 	 * work here (if we can support an older interface version - that,
 	 * of course, also affects the "if" above).
 	 */
-	pIf->oID = OBJvmstk;
+	//xxxpIf->oID = OBJvmstk;
 
 	pIf->Construct = vmstkConstruct;
 	pIf->ConstructFinalize = vmstkConstructFinalize;
@@ -224,7 +224,7 @@ ENDobjQueryInterface(vmstk)
  */
 BEGINObjClassInit(vmstk, 1, OBJ_IS_CORE_MODULE) /* class, version */
 	/* request objects we use */
-	CHKiRet(objUse(var));
+	CHKiRet(objUse(var, CORE_COMPONENT));
 
 	/* set our own handlers */
 	OBJSetMethodHandler(objMethod_DEBUGPRINT, vmstkDebugPrint);
diff --git a/wti.c b/wti.c
index fab52327..9fadfdf3 100644
--- a/wti.c
+++ b/wti.c
@@ -453,6 +453,10 @@ finalize_it:
 }
 
 
+/* dummy */
+rsRetVal wtiQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
+
+
 /* Initialize the wti class. Must be called as the very first method
  * before anything else is called inside this class.
  * rgerhards, 2008-01-09
diff --git a/wtp.c b/wtp.c
index 6094d469..83cb5d5e 100644
--- a/wtp.c
+++ b/wtp.c
@@ -604,6 +604,9 @@ finalize_it:
 	RETiRet;
 }
 
+/* dummy */
+rsRetVal wtpQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
+
 /* Initialize the stream class. Must be called as the very first method
  * before anything else is called inside this class.
  * rgerhards, 2008-01-09
-- 
cgit