Add DeqpPlatformCapabilityQueryInstrumentation.

- Add Instrumentation for querying if the described render target is supported.
- Move chooseConfig() from egluGLContextFactory to egluGLUtil

Change-Id: I5f55d0d7c2c1f6c70de9333e42298deb32f19953
diff --git a/Android.mk b/Android.mk
index 3e7c45f..05e5d3b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -186,6 +186,7 @@
 	framework/platform/android/tcuAndroidMain.cpp \
 	framework/platform/android/tcuAndroidNativeActivity.cpp \
 	framework/platform/android/tcuAndroidPlatform.cpp \
+	framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp \
 	framework/platform/android/tcuAndroidRenderActivity.cpp \
 	framework/platform/android/tcuAndroidTestActivity.cpp \
 	framework/platform/android/tcuAndroidUtil.cpp \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4e55b4..2453628 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -296,7 +296,7 @@
 if (DE_OS_IS_ANDROID)
 	include_directories(executor)
 
-	add_library(deqp SHARED framework/platform/android/tcuAndroidMain.cpp framework/platform/android/tcuAndroidJNI.cpp framework/platform/android/tcuTestLogParserJNI.cpp ${DEQP_MODULE_ENTRY_POINTS})
+	add_library(deqp SHARED framework/platform/android/tcuAndroidMain.cpp framework/platform/android/tcuAndroidJNI.cpp framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp framework/platform/android/tcuTestLogParserJNI.cpp ${DEQP_MODULE_ENTRY_POINTS})
 	target_link_libraries(deqp tcutil-platform xecore ${DEQP_MODULE_LIBRARIES})
 
 elseif (DE_OS_IS_IOS)
diff --git a/android/package/AndroidManifest.xml b/android/package/AndroidManifest.xml
index 4da88a1..4bc0d4b 100644
--- a/android/package/AndroidManifest.xml
+++ b/android/package/AndroidManifest.xml
@@ -50,4 +50,7 @@
 	<instrumentation android:label="dEQP-Instrumentation"
 					 android:name="com.drawelements.deqp.testercore.DeqpInstrumentation"
 					 android:targetPackage="com.drawelements.deqp" />
+	<instrumentation android:label="dEQP-PlatformCapabilityQueryInstrumentation"
+					 android:name="com.drawelements.deqp.platformutil.DeqpPlatformCapabilityQueryInstrumentation"
+					 android:targetPackage="com.drawelements.deqp" />
 </manifest>
diff --git a/android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java b/android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java
new file mode 100644
index 0000000..04e3c1c
--- /dev/null
+++ b/android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Platform Utilites
+ * ----------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief dEQP platform capability query instrumentation
+ *//*--------------------------------------------------------------------*/
+
+package com.drawelements.deqp.platformutil;
+
+import android.app.Instrumentation;
+
+import android.os.Bundle;
+
+public class DeqpPlatformCapabilityQueryInstrumentation extends Instrumentation
+{
+	static
+	{
+		System.loadLibrary("deqp");
+	}
+
+	private static final String	LOG_TAG							= "dEQP/PlatformCapabilityQueryInstrumentation";
+	private static final int	CONFIGQUERYRESULT_SUPPORTED		= 0;
+	private static final int	CONFIGQUERYRESULT_NOT_SUPPORTED	= 1;
+	private static final int	CONFIGQUERYRESULT_GENERIC_ERROR	= -1;
+
+	private String				m_cmdLine;
+	private String				m_queryType;
+
+	@Override
+	public void onCreate (Bundle arguments) {
+		super.onCreate(arguments);
+		start();
+
+		m_queryType = arguments.getString("deqpQueryType");
+		m_cmdLine = arguments.getString("deqpCmdLine");
+	}
+
+	@Override
+	public void onStart () {
+		super.onStart();
+
+		Bundle resultInfo;
+		int resultCode = 0;
+
+		try
+		{
+			if ("renderConfigSupported".equals(m_queryType))
+				resultInfo = doRenderConfigSupportedQuery();
+			else
+			{
+				resultInfo = new Bundle();
+				resultInfo.putString("Error", "unknown query");
+				resultCode = 2;
+			}
+		}
+		catch (Exception e)
+		{
+			resultInfo = new Bundle();
+			resultInfo.putString("Error", e.getMessage());
+			resultCode = 1;
+		}
+
+		finish(resultCode, resultInfo);
+	}
+
+	private Bundle doRenderConfigSupportedQuery ()
+	{
+		if (m_cmdLine == null)
+			throw new RuntimeException("missing command line");
+
+		final int result = nativeRenderConfigSupportedQuery(m_cmdLine);
+
+		if (result == CONFIGQUERYRESULT_SUPPORTED)
+		{
+			final Bundle resultInfo = new Bundle();
+			resultInfo.putString("Supported", "Yes");
+			return resultInfo;
+		}
+		else if (result == CONFIGQUERYRESULT_NOT_SUPPORTED)
+		{
+			final Bundle resultInfo = new Bundle();
+			resultInfo.putString("Supported", "No");
+			return resultInfo;
+		}
+		else if (result == CONFIGQUERYRESULT_GENERIC_ERROR)
+			throw new RuntimeException("platform query reported failure");
+		else
+			throw new RuntimeException("platform query returned out-of-range result");
+	}
+
+	private static native int nativeRenderConfigSupportedQuery (String cmdLine);
+}
diff --git a/framework/common/tcuCommandLine.cpp b/framework/common/tcuCommandLine.cpp
index 9c25f31..405d9bd 100644
--- a/framework/common/tcuCommandLine.cpp
+++ b/framework/common/tcuCommandLine.cpp
@@ -675,6 +675,16 @@
 	m_caseTree = DE_NULL;
 }
 
+const de::cmdline::CommandLine& CommandLine::getCommandLine (void) const
+{
+	return m_cmdLine;
+}
+
+void CommandLine::registerExtendedOptions (de::cmdline::Parser& parser)
+{
+	DE_UNREF(parser);
+}
+
 /*--------------------------------------------------------------------*//*!
  * \brief Parse command line from standard argc, argv pair.
  * \note parse() must be called exactly once.
@@ -689,6 +699,7 @@
 
 	opt::registerOptions(parser);
 	opt::registerLegacyOptions(parser);
+	registerExtendedOptions(parser);
 
 	clear();
 
diff --git a/framework/common/tcuCommandLine.hpp b/framework/common/tcuCommandLine.hpp
index 961b563..1685e90 100644
--- a/framework/common/tcuCommandLine.hpp
+++ b/framework/common/tcuCommandLine.hpp
@@ -181,12 +181,17 @@
 	//! Check if test case is in supplied test case list.
 	bool							checkTestCaseName			(const char* caseName) const;
 
+protected:
+	const de::cmdline::CommandLine&	getCommandLine				(void) const;
+
 private:
 									CommandLine					(const CommandLine&);	// not allowed!
 	CommandLine&					operator=					(const CommandLine&);	// not allowed!
 
 	void							clear						(void);
 
+	virtual void					registerExtendedOptions		(de::cmdline::Parser& parser);
+
 	de::cmdline::CommandLine		m_cmdLine;
 	deUint32						m_logFlags;
 	CaseTreeNode*					m_caseTree;
diff --git a/framework/egl/egluGLContextFactory.cpp b/framework/egl/egluGLContextFactory.cpp
index f192ee7..5885381 100644
--- a/framework/egl/egluGLContextFactory.cpp
+++ b/framework/egl/egluGLContextFactory.cpp
@@ -202,85 +202,6 @@
 	delete m_dynamicGLLibrary;
 }
 
-bool configMatches (const Library& egl, EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& renderConfig)
-{
-	// \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
-
-	{
-		EGLint		renderableType		= 0;
-		EGLint		requiredRenderable	= apiRenderableType(renderConfig.type.getAPI());
-
-		EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
-
-		if ((renderableType & requiredRenderable) == 0)
-			return false;
-	}
-
-	if (renderConfig.surfaceType != (glu::RenderConfig::SurfaceType)glu::RenderConfig::DONT_CARE)
-	{
-		EGLint		surfaceType		= 0;
-		EGLint		requiredSurface	= 0;
-
-		switch (renderConfig.surfaceType)
-		{
-			case glu::RenderConfig::SURFACETYPE_WINDOW:				requiredSurface = EGL_WINDOW_BIT;	break;
-			case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:	requiredSurface = EGL_PIXMAP_BIT;	break;
-			case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:	requiredSurface = EGL_PBUFFER_BIT;	break;
-			default:
-				DE_ASSERT(false);
-		}
-
-		EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
-
-		if ((surfaceType & requiredSurface) == 0)
-			return false;
-	}
-
-	{
-		static const struct
-		{
-			int	glu::RenderConfig::*field;
-			EGLint attrib;
-		} s_attribs[] =
-		{
-			{ &glu::RenderConfig::id,			EGL_CONFIG_ID		},
-			{ &glu::RenderConfig::redBits,		EGL_RED_SIZE		},
-			{ &glu::RenderConfig::greenBits,	EGL_GREEN_SIZE		},
-			{ &glu::RenderConfig::blueBits,		EGL_BLUE_SIZE		},
-			{ &glu::RenderConfig::alphaBits,	EGL_ALPHA_SIZE		},
-			{ &glu::RenderConfig::depthBits,	EGL_DEPTH_SIZE		},
-			{ &glu::RenderConfig::stencilBits,	EGL_STENCIL_SIZE	},
-			{ &glu::RenderConfig::numSamples,	EGL_SAMPLES			},
-		};
-
-		for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
-		{
-			if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
-			{
-				EGLint value = 0;
-				EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
-				if (value != renderConfig.*s_attribs[attribNdx].field)
-					return false;
-			}
-		}
-	}
-
-	return true;
-}
-
-EGLConfig chooseConfig (const Library& egl, EGLDisplay display, const glu::RenderConfig& config)
-{
-	const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display);
-
-	for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
-	{
-		if (configMatches(egl, display, *iter, config))
-			return *iter;
-	}
-
-	throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
-}
-
 static WindowParams::Visibility getNativeWindowVisibility (glu::RenderConfig::Visibility visibility)
 {
 	using glu::RenderConfig;
diff --git a/framework/egl/egluGLUtil.cpp b/framework/egl/egluGLUtil.cpp
index 18ec6d2..0f65b6d 100644
--- a/framework/egl/egluGLUtil.cpp
+++ b/framework/egl/egluGLUtil.cpp
@@ -155,4 +155,83 @@
 	return context;
 }
 
+static bool configMatches (const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig eglConfig, const glu::RenderConfig& renderConfig)
+{
+	// \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
+
+	{
+		EGLint		renderableType		= 0;
+		EGLint		requiredRenderable	= apiRenderableType(renderConfig.type.getAPI());
+
+		EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
+
+		if ((renderableType & requiredRenderable) == 0)
+			return false;
+	}
+
+	if (renderConfig.surfaceType != (glu::RenderConfig::SurfaceType)glu::RenderConfig::DONT_CARE)
+	{
+		EGLint		surfaceType		= 0;
+		EGLint		requiredSurface	= 0;
+
+		switch (renderConfig.surfaceType)
+		{
+			case glu::RenderConfig::SURFACETYPE_WINDOW:				requiredSurface = EGL_WINDOW_BIT;	break;
+			case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:	requiredSurface = EGL_PIXMAP_BIT;	break;
+			case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:	requiredSurface = EGL_PBUFFER_BIT;	break;
+			default:
+				DE_ASSERT(false);
+		}
+
+		EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
+
+		if ((surfaceType & requiredSurface) == 0)
+			return false;
+	}
+
+	{
+		static const struct
+		{
+			int	glu::RenderConfig::*field;
+			EGLint attrib;
+		} s_attribs[] =
+		{
+			{ &glu::RenderConfig::id,			EGL_CONFIG_ID		},
+			{ &glu::RenderConfig::redBits,		EGL_RED_SIZE		},
+			{ &glu::RenderConfig::greenBits,	EGL_GREEN_SIZE		},
+			{ &glu::RenderConfig::blueBits,		EGL_BLUE_SIZE		},
+			{ &glu::RenderConfig::alphaBits,	EGL_ALPHA_SIZE		},
+			{ &glu::RenderConfig::depthBits,	EGL_DEPTH_SIZE		},
+			{ &glu::RenderConfig::stencilBits,	EGL_STENCIL_SIZE	},
+			{ &glu::RenderConfig::numSamples,	EGL_SAMPLES			},
+		};
+
+		for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
+		{
+			if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
+			{
+				EGLint value = 0;
+				EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
+				if (value != renderConfig.*s_attribs[attribNdx].field)
+					return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+EGLConfig chooseConfig (const Library& egl, EGLDisplay display, const glu::RenderConfig& config)
+{
+	const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display);
+
+	for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
+	{
+		if (configMatches(egl, display, *iter, config))
+			return *iter;
+	}
+
+	throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
+}
+
 }
diff --git a/framework/egl/egluGLUtil.hpp b/framework/egl/egluGLUtil.hpp
index 395ea2e..e0db6ba 100644
--- a/framework/egl/egluGLUtil.hpp
+++ b/framework/egl/egluGLUtil.hpp
@@ -40,6 +40,7 @@
 glw::GLenum			getImageGLTarget		(eglw::EGLenum source);
 eglw::EGLint		apiRenderableType 		(glu::ApiType apiType);
 eglw::EGLContext	createGLContext			(const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig config, const glu::ContextType& contextType);
+eglw::EGLConfig		chooseConfig			(const eglw::Library& egl, eglw::EGLDisplay display, const glu::RenderConfig& config);
 
 }
 
diff --git a/framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp b/framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp
new file mode 100644
index 0000000..83e047d
--- /dev/null
+++ b/framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp
@@ -0,0 +1,217 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Platform Utilites
+ * ----------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Android platform capability query JNI component
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+
+#include "tcuCommandLine.hpp"
+#include "gluRenderConfig.hpp"
+#include "gluRenderContext.hpp"
+#include "eglwLibrary.hpp"
+#include "eglwEnums.hpp"
+#include "egluUtil.hpp"
+#include "egluGLUtil.hpp"
+
+#include <jni.h>
+
+namespace
+{
+namespace opt
+{
+
+DE_DECLARE_COMMAND_LINE_OPT(GLMajorVersion, int);
+DE_DECLARE_COMMAND_LINE_OPT(GLMinorVersion, int);
+
+} // opt
+
+class GLConfigParser : public tcu::CommandLine
+{
+public:
+					GLConfigParser			(const std::string& argString);
+
+	bool			hasGLMajorVersion		(void) const;
+	bool			hasGLMinorVersion		(void) const;
+	int				getGLMajorVersion		(void) const;
+	int				getGLMinorVersion		(void) const;
+
+private:
+	virtual void	registerExtendedOptions	(de::cmdline::Parser& parser);
+};
+
+GLConfigParser::GLConfigParser (const std::string& argString)
+{
+	const std::string execString = "fakebinaryname " + argString; // convert argument list to full command line
+
+	if (!parse(execString))
+	{
+		tcu::print("failed to parse command line");
+		TCU_THROW(Exception, "failed to parse command line");
+	}
+}
+
+bool GLConfigParser::hasGLMajorVersion (void) const
+{
+	return getCommandLine().hasOption<opt::GLMajorVersion>();
+}
+
+bool GLConfigParser::hasGLMinorVersion (void) const
+{
+	return getCommandLine().hasOption<opt::GLMinorVersion>();
+}
+
+int GLConfigParser::getGLMajorVersion (void) const
+{
+	DE_ASSERT(hasGLMajorVersion());
+	return getCommandLine().getOption<opt::GLMajorVersion>();
+}
+
+int GLConfigParser::getGLMinorVersion (void) const
+{
+	DE_ASSERT(hasGLMinorVersion());
+	return getCommandLine().getOption<opt::GLMinorVersion>();
+}
+
+void GLConfigParser::registerExtendedOptions (de::cmdline::Parser& parser)
+{
+	using de::cmdline::Option;
+
+	parser
+		<< Option<opt::GLMajorVersion>	(DE_NULL, "deqp-gl-major-version", "OpenGL ES Major version")
+		<< Option<opt::GLMinorVersion>	(DE_NULL, "deqp-gl-minor-version", "OpenGL ES Minor version");
+}
+
+glu::RenderConfig parseRenderConfig (const std::string& argsStr)
+{
+	const GLConfigParser parsedCommandLine (argsStr);
+
+	if (!parsedCommandLine.hasGLMajorVersion() ||
+		!parsedCommandLine.hasGLMinorVersion())
+	{
+		tcu::print("minor and major version must be supplied");
+		TCU_THROW(Exception, "minor and major version must be supplied");
+	}
+	else
+	{
+		const glu::ContextType	testContextType	(glu::ApiType::es(parsedCommandLine.getGLMajorVersion(), parsedCommandLine.getGLMinorVersion()));
+		glu::RenderConfig		renderConfig	(testContextType);
+
+		glu::parseRenderConfig(&renderConfig, parsedCommandLine);
+
+		return renderConfig;
+	}
+}
+
+bool isRenderConfigSupported (const std::string& cmdLineStr)
+{
+	const glu::RenderConfig		renderConfig	= parseRenderConfig(cmdLineStr);
+	const eglw::DefaultLibrary	egl;
+	const eglw::EGLDisplay		display			= egl.getDisplay(EGL_DEFAULT_DISPLAY);
+	eglw::EGLint				eglMajor		= -1;
+	eglw::EGLint				eglMinor		= -1;
+
+	if (display == EGL_NO_DISPLAY)
+	{
+		tcu::print("could not get default display");
+		TCU_THROW(Exception, "could not get default display");
+	}
+
+	if (egl.initialize(display, &eglMajor, &eglMinor) != EGL_TRUE)
+	{
+		tcu::print("failed to initialize egl");
+		TCU_THROW(Exception, "failed to initialize egl");
+	}
+	tcu::print("EGL initialized, major=%d, minor=%d", eglMajor, eglMinor);
+
+	try
+	{
+		// ignoring return value
+		(void)eglu::chooseConfig(egl, display, renderConfig);
+	}
+	catch (const tcu::NotSupportedError&)
+	{
+		tcu::print("No matching config");
+		egl.terminate(display);
+		return false;
+	}
+	catch (...)
+	{
+		egl.terminate(display);
+		throw;
+	}
+	egl.terminate(display);
+
+	return true;
+}
+
+} // anonymous
+
+
+DE_BEGIN_EXTERN_C
+
+JNIEXPORT jint JNICALL Java_com_drawelements_deqp_platformutil_DeqpPlatformCapabilityQueryInstrumentation_nativeRenderConfigSupportedQuery (JNIEnv* env, jclass, jstring jCmdLine)
+{
+	enum
+	{
+		CONFIGQUERYRESULT_SUPPORTED = 0,
+		CONFIGQUERYRESULT_NOT_SUPPORTED = 1,
+		CONFIGQUERYRESULT_GENERIC_ERROR = -1,
+	};
+
+	std::string			cmdLine;
+	const char* const	cmdLineBytes = env->GetStringUTFChars(jCmdLine, DE_NULL);
+
+	if (cmdLineBytes == DE_NULL)
+	{
+		// no command line is not executable
+		tcu::print("no command line supplied");
+		return CONFIGQUERYRESULT_GENERIC_ERROR;
+	}
+
+	try
+	{
+		// try to copy to local buffer
+		cmdLine = std::string(cmdLineBytes);
+	}
+	catch (const std::bad_alloc&)
+	{
+		env->ReleaseStringUTFChars(jCmdLine, cmdLineBytes);
+		tcu::print("failed to copy cmdLine");
+		return CONFIGQUERYRESULT_GENERIC_ERROR;
+	}
+	env->ReleaseStringUTFChars(jCmdLine, cmdLineBytes);
+
+	try
+	{
+		const bool isSupported = isRenderConfigSupported(cmdLine);
+
+		return (isSupported) ? (CONFIGQUERYRESULT_SUPPORTED)
+		                     : (CONFIGQUERYRESULT_NOT_SUPPORTED);
+	}
+	catch (const std::exception& ex)
+	{
+		// don't bother forwarding the exception to the caller. They cannot do anything with the exception anyway.
+		tcu::print("Error: %s", ex.what());
+		return CONFIGQUERYRESULT_GENERIC_ERROR;
+	}
+}
+
+DE_END_EXTERN_C