kerneltest/e32test/dll/t_nestdll.cpp
changeset 300 1d28c8722707
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/dll/t_nestdll.cpp	Tue Nov 02 15:29:23 2010 +0000
@@ -0,0 +1,91 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\dll\t_nestdll.cpp
+// 
+//
+
+#include <e32std.h>
+#include <e32debug.h>
+#include <e32svr.h>
+
+// Utility macros for stringification, long-stringification, and token pasting
+// These are indirected so that if you call them on things which are also macros,
+// the macros are expanded first.
+#define STRINGIFY_(x) #x
+#define STRINGIFY(x) STRINGIFY_(x)
+#define LSTRINGIFY_(x) L ## #x
+#define LSTRINGIFY(x) LSTRINGIFY_(x)
+#define PASTE_(x,y) x ## y
+#define PASTE(x,y) PASTE_(x,y)
+
+// Declare the imported functions for the DLLs we statically link to
+#ifdef LINK_TO
+IMPORT_C TInt PASTE(DataForDLL,LINK_TO)();
+#endif
+
+// Dummy class just to get a constructor into the binary
+class ConstructorTest
+	{
+public:
+	ConstructorTest();
+	};
+
+// Constructor, which should be called exactly once per DLL
+ConstructorTest::ConstructorTest()
+	{
+	RDebug::Printf("In constructor for DLL " STRINGIFY(DLL_NUMBER));
+
+	// Call the imported functions for the DLL we statically link to.
+	// This is just to get them into the import table.
+#ifdef LINK_TO
+	PASTE(DataForDLL,LINK_TO)();
+#endif
+
+	// Use DLL TLS handle zero to fake a global data object
+	TInt* loadOrder = (TInt*)UserSvr::DllTls(0);
+	if (!loadOrder)
+		{
+		// If we're the first constructor, allocate an array and zero it
+		loadOrder = new TInt[100];
+		for (TInt i = 0; i < 100; ++i)
+			loadOrder[i] = 0;
+		UserSvr::DllSetTls(0, loadOrder);
+		}
+
+	// Find the first zero entry in the load order array and add our index
+	TInt next = 0;
+	while (loadOrder[next] != 0)
+		++next;
+	loadOrder[next] = DLL_NUMBER;
+
+	// If we're supposed to be doing a nested DLL load, do it here.
+	// You aren't supposed to leave in a constructor but it causes an
+	// identifiable panic, to distinguish it from any other possible crash.
+#ifdef LOAD_DLL
+	RDebug::Printf("Doing nested DLL load");
+	RLibrary lib;
+	TInt r = lib.Load(TPtrC16((const TText*)(L"t_nestdll" LSTRINGIFY(LOAD_DLL) L".dll")));
+	RDebug::Printf("Nested DLL load returned %d", r);
+	User::LeaveIfError(r);
+#endif
+	}
+
+// Global instance of the dummy object
+ConstructorTest constructor_test;
+
+// The exported function for this DLL, which just tells you how many times the constructor was called
+EXPORT_C TInt PASTE(DataForDLL,DLL_NUMBER)()
+	{
+	return 0;
+	}