kerneltest/e32test/dll/t_nestdll.cpp
author hgs
Tue, 02 Nov 2010 15:29:23 +0000
changeset 300 1d28c8722707
permissions -rw-r--r--
201043_09

// 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;
	}