xref: /haiku/src/kits/support/Archivable.cpp (revision 13bbfe422b13d808b182a3abf187800d4d80e631)
19ecf9d1cSIngo Weinhold /*
289eb861aSAxel Dörfler  * Copyright (c) 2001-2008, Haiku, Inc.
39ecf9d1cSIngo Weinhold  * Distributed under the terms of the MIT License.
49ecf9d1cSIngo Weinhold  *
59ecf9d1cSIngo Weinhold  * Authors:
69ecf9d1cSIngo Weinhold  *		Erik Jaesler (erik@cgsoftware.com)
79ecf9d1cSIngo Weinhold  */
852a38012Sejakowatz 
97bc5a06bSAxel Dörfler /*!	BArchivable mix-in class defines the archiving protocol.
107bc5a06bSAxel Dörfler 	Also some global archiving functions.
117bc5a06bSAxel Dörfler */
129ecf9d1cSIngo Weinhold 
139ecf9d1cSIngo Weinhold 
1452a38012Sejakowatz #include <ctype.h>
1552a38012Sejakowatz #include <errno.h>
1652a38012Sejakowatz #include <stdlib.h>
1752a38012Sejakowatz #include <stdio.h>
1852a38012Sejakowatz #include <string>
197bc5a06bSAxel Dörfler #include <syslog.h>
2052a38012Sejakowatz #include <typeinfo>
2152a38012Sejakowatz #include <vector>
2252a38012Sejakowatz 
2352a38012Sejakowatz #include <AppFileInfo.h>
2452a38012Sejakowatz #include <Archivable.h>
2552a38012Sejakowatz #include <Entry.h>
2652a38012Sejakowatz #include <List.h>
2752a38012Sejakowatz #include <OS.h>
2852a38012Sejakowatz #include <Path.h>
2952a38012Sejakowatz #include <Roster.h>
3052a38012Sejakowatz #include <String.h>
3152a38012Sejakowatz 
3252a38012Sejakowatz 
3352a38012Sejakowatz using std::string;
3452a38012Sejakowatz using std::vector;
3552a38012Sejakowatz 
3652a38012Sejakowatz const char* B_CLASS_FIELD = "class";
3752a38012Sejakowatz const char* B_ADD_ON_FIELD = "add_on";
3852a38012Sejakowatz const int32 FUNC_NAME_LEN = 1024;
3952a38012Sejakowatz 
407bc5a06bSAxel Dörfler // TODO: consider moving these to a separate module, and making them more
417bc5a06bSAxel Dörfler //	full-featured (e.g., taking NS::ClassName::Function(Param p) instead
427bc5a06bSAxel Dörfler //	of just NS::ClassName)
4352a38012Sejakowatz 
449ecf9d1cSIngo Weinhold 
45*13bbfe42SAxel Dörfler static status_t
4689eb861aSAxel Dörfler demangle_class_name(const char* name, BString& out)
4752a38012Sejakowatz {
4852a38012Sejakowatz // TODO: add support for template classes
4952a38012Sejakowatz //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
5052a38012Sejakowatz 
5152a38012Sejakowatz 	out = "";
5252a38012Sejakowatz 
53*13bbfe42SAxel Dörfler 	if (name[0] == 'Q') {
54*13bbfe42SAxel Dörfler 		// The name is in a namespace
55*13bbfe42SAxel Dörfler 		int namespaceCount = 0;
56*13bbfe42SAxel Dörfler 		name++;
57*13bbfe42SAxel Dörfler 		if (name[0] == '_') {
58*13bbfe42SAxel Dörfler 			// more than 10 namespaces deep
59*13bbfe42SAxel Dörfler 			if (!isdigit(*++name))
60*13bbfe42SAxel Dörfler 				return B_BAD_VALUE;
6152a38012Sejakowatz 
62*13bbfe42SAxel Dörfler 			namespaceCount = strtoul(name, (char**)&name, 10);
63*13bbfe42SAxel Dörfler 			if (name[0] != '_')
64*13bbfe42SAxel Dörfler 				return B_BAD_VALUE;
65*13bbfe42SAxel Dörfler 		} else
66*13bbfe42SAxel Dörfler 			namespaceCount = name[0] - '0';
6752a38012Sejakowatz 
68*13bbfe42SAxel Dörfler 		name++;
6952a38012Sejakowatz 
70*13bbfe42SAxel Dörfler 		for (int i = 0; i < namespaceCount - 1; i++) {
71*13bbfe42SAxel Dörfler 			if (!isdigit(name[0]))
72*13bbfe42SAxel Dörfler 				return B_BAD_VALUE;
73*13bbfe42SAxel Dörfler 
74*13bbfe42SAxel Dörfler 			int nameLength = strtoul(name, (char**)&name, 10);
75*13bbfe42SAxel Dörfler 			out.Append(name, nameLength);
7652a38012Sejakowatz 			out += "::";
77*13bbfe42SAxel Dörfler 			name += nameLength;
7852a38012Sejakowatz 		}
7952a38012Sejakowatz 	}
8052a38012Sejakowatz 
81*13bbfe42SAxel Dörfler 	int nameLength = strtoul(name, (char**)&name, 10);
82*13bbfe42SAxel Dörfler 	out.Append(name, nameLength);
83*13bbfe42SAxel Dörfler 
84*13bbfe42SAxel Dörfler 	return B_OK;
8552a38012Sejakowatz }
869ecf9d1cSIngo Weinhold 
879ecf9d1cSIngo Weinhold 
8889eb861aSAxel Dörfler static void
8989eb861aSAxel Dörfler mangle_class_name(const char* name, BString& out)
9052a38012Sejakowatz {
9152a38012Sejakowatz // TODO: add support for template classes
9252a38012Sejakowatz //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
9352a38012Sejakowatz 
9452a38012Sejakowatz 	//	Chop this:
9552a38012Sejakowatz 	//		testthree::testfour::Testthree::Testfour
9652a38012Sejakowatz 	//	up into little bite-sized pieces
9752a38012Sejakowatz 	int count = 0;
9852a38012Sejakowatz 	string origName(name);
9952a38012Sejakowatz 	vector<string> spacenames;
10052a38012Sejakowatz 
10152a38012Sejakowatz 	string::size_type pos = 0;
10252a38012Sejakowatz 	string::size_type oldpos = 0;
1039ecf9d1cSIngo Weinhold 	while (pos != string::npos) {
10452a38012Sejakowatz 		pos = origName.find_first_of("::", oldpos);
10552a38012Sejakowatz 		spacenames.push_back(string(origName, oldpos, pos - oldpos));
10652a38012Sejakowatz 		pos = origName.find_first_not_of("::", pos);
10752a38012Sejakowatz 		oldpos = pos;
10852a38012Sejakowatz 		++count;
10952a38012Sejakowatz 	}
11052a38012Sejakowatz 
11152a38012Sejakowatz 	//	Now mangle it into this:
11252a38012Sejakowatz 	//		Q49testthree8testfour9Testthree8Testfour
11352a38012Sejakowatz 	out = "";
1149ecf9d1cSIngo Weinhold 	if (count > 1) {
11552a38012Sejakowatz 		out += 'Q';
11652a38012Sejakowatz 		if (count > 10)
11752a38012Sejakowatz 			out += '_';
11852a38012Sejakowatz 		out << count;
11952a38012Sejakowatz 		if (count > 10)
12052a38012Sejakowatz 			out += '_';
12152a38012Sejakowatz 	}
12252a38012Sejakowatz 
1239ecf9d1cSIngo Weinhold 	for (unsigned int i = 0; i < spacenames.size(); ++i) {
12452a38012Sejakowatz 		out << (int)spacenames[i].length();
12552a38012Sejakowatz 		out += spacenames[i].c_str();
12652a38012Sejakowatz 	}
12752a38012Sejakowatz }
1289ecf9d1cSIngo Weinhold 
1299ecf9d1cSIngo Weinhold 
13089eb861aSAxel Dörfler static void
13189eb861aSAxel Dörfler build_function_name(const BString& className, BString& funcName)
13252a38012Sejakowatz {
13389eb861aSAxel Dörfler 	funcName = "";
13452a38012Sejakowatz 
13589eb861aSAxel Dörfler 	//	This is what we're after:
13689eb861aSAxel Dörfler 	//		Instantiate__Q28OpenBeOS11BArchivableP8BMessage
13789eb861aSAxel Dörfler 	mangle_class_name(className.String(), funcName);
13889eb861aSAxel Dörfler #if __GNUC__ >= 4
13989eb861aSAxel Dörfler 	funcName.Prepend("_ZN");
14089eb861aSAxel Dörfler 	funcName.Append("11InstantiateE");
14189eb861aSAxel Dörfler #else
14289eb861aSAxel Dörfler 	funcName.Prepend("Instantiate__");
14352a38012Sejakowatz #endif
14489eb861aSAxel Dörfler 	funcName.Append("P8BMessage");
14552a38012Sejakowatz }
14652a38012Sejakowatz 
14789eb861aSAxel Dörfler 
14889eb861aSAxel Dörfler static bool
14989eb861aSAxel Dörfler add_private_namespace(BString& name)
15089eb861aSAxel Dörfler {
15189eb861aSAxel Dörfler 	if (name.Compare("_", 1) != 0)
15289eb861aSAxel Dörfler 		return false;
15389eb861aSAxel Dörfler 
15489eb861aSAxel Dörfler 	name.Prepend("BPrivate::");
15589eb861aSAxel Dörfler 	return true;
15689eb861aSAxel Dörfler }
15789eb861aSAxel Dörfler 
15889eb861aSAxel Dörfler 
15989eb861aSAxel Dörfler static instantiation_func
16089eb861aSAxel Dörfler find_function_in_image(BString& funcName, image_id id, status_t& err)
16189eb861aSAxel Dörfler {
16289eb861aSAxel Dörfler 	instantiation_func instantiationFunc = NULL;
16389eb861aSAxel Dörfler 	err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT,
16489eb861aSAxel Dörfler 		(void**)&instantiationFunc);
16589eb861aSAxel Dörfler 	if (err != B_OK)
16689eb861aSAxel Dörfler 		return NULL;
16789eb861aSAxel Dörfler 
16889eb861aSAxel Dörfler 	return instantiationFunc;
16989eb861aSAxel Dörfler }
17089eb861aSAxel Dörfler 
17189eb861aSAxel Dörfler 
17289eb861aSAxel Dörfler static status_t
17389eb861aSAxel Dörfler check_signature(const char* signature, image_info& info)
17489eb861aSAxel Dörfler {
17589eb861aSAxel Dörfler 	if (signature == NULL) {
17689eb861aSAxel Dörfler 		// If it wasn't specified, anything "matches"
17789eb861aSAxel Dörfler 		return B_OK;
17889eb861aSAxel Dörfler 	}
17989eb861aSAxel Dörfler 
18089eb861aSAxel Dörfler 	// Get image signature
18189eb861aSAxel Dörfler 	BFile file(info.name, B_READ_ONLY);
18289eb861aSAxel Dörfler 	status_t err = file.InitCheck();
18389eb861aSAxel Dörfler 	if (err != B_OK)
18489eb861aSAxel Dörfler 		return err;
18589eb861aSAxel Dörfler 
18689eb861aSAxel Dörfler 	char imageSignature[B_MIME_TYPE_LENGTH];
18789eb861aSAxel Dörfler 	BAppFileInfo appFileInfo(&file);
18889eb861aSAxel Dörfler 	err = appFileInfo.GetSignature(imageSignature);
18989eb861aSAxel Dörfler 	if (err != B_OK) {
19089eb861aSAxel Dörfler 		syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s",
19189eb861aSAxel Dörfler 			info.name);
19289eb861aSAxel Dörfler 		return err;
19389eb861aSAxel Dörfler 	}
19489eb861aSAxel Dörfler 
19589eb861aSAxel Dörfler 	if (strcmp(signature, imageSignature))
19689eb861aSAxel Dörfler 		return B_MISMATCHED_VALUES;
19789eb861aSAxel Dörfler 
19889eb861aSAxel Dörfler 	return B_OK;
19989eb861aSAxel Dörfler }
20089eb861aSAxel Dörfler 
20189eb861aSAxel Dörfler 
20289eb861aSAxel Dörfler //	#pragma mark -
20389eb861aSAxel Dörfler 
20489eb861aSAxel Dörfler 
20589eb861aSAxel Dörfler BArchivable::BArchivable()
20689eb861aSAxel Dörfler {
20789eb861aSAxel Dörfler }
20889eb861aSAxel Dörfler 
20989eb861aSAxel Dörfler 
21089eb861aSAxel Dörfler BArchivable::BArchivable(BMessage* from)
21189eb861aSAxel Dörfler {
21289eb861aSAxel Dörfler }
21389eb861aSAxel Dörfler 
21489eb861aSAxel Dörfler 
21589eb861aSAxel Dörfler BArchivable::~BArchivable()
21689eb861aSAxel Dörfler {
21789eb861aSAxel Dörfler }
21889eb861aSAxel Dörfler 
21989eb861aSAxel Dörfler 
22089eb861aSAxel Dörfler status_t
22189eb861aSAxel Dörfler BArchivable::Archive(BMessage* into, bool deep) const
22289eb861aSAxel Dörfler {
22389eb861aSAxel Dörfler 	if (!into) {
22489eb861aSAxel Dörfler 		// TODO: logging/other error reporting?
22589eb861aSAxel Dörfler 		return B_BAD_VALUE;
22689eb861aSAxel Dörfler 	}
22789eb861aSAxel Dörfler 
22889eb861aSAxel Dörfler 	BString name;
229*13bbfe42SAxel Dörfler 	status_t status = demangle_class_name(typeid(*this).name(), name);
230*13bbfe42SAxel Dörfler 	if (status != B_OK)
231*13bbfe42SAxel Dörfler 		return status;
23289eb861aSAxel Dörfler 
23389eb861aSAxel Dörfler 	return into->AddString(B_CLASS_FIELD, name);
23489eb861aSAxel Dörfler }
23589eb861aSAxel Dörfler 
23689eb861aSAxel Dörfler 
23789eb861aSAxel Dörfler BArchivable*
23889eb861aSAxel Dörfler BArchivable::Instantiate(BMessage* from)
23989eb861aSAxel Dörfler {
24089eb861aSAxel Dörfler 	debugger("Can't create a plain BArchivable object");
24189eb861aSAxel Dörfler 	return NULL;
24289eb861aSAxel Dörfler }
24389eb861aSAxel Dörfler 
24489eb861aSAxel Dörfler 
24589eb861aSAxel Dörfler status_t
24689eb861aSAxel Dörfler BArchivable::Perform(perform_code d, void* arg)
24789eb861aSAxel Dörfler {
24889eb861aSAxel Dörfler 	// TODO: Check against original
24989eb861aSAxel Dörfler 	return B_ERROR;
25089eb861aSAxel Dörfler }
25189eb861aSAxel Dörfler 
25289eb861aSAxel Dörfler 
25389eb861aSAxel Dörfler void BArchivable::_ReservedArchivable1() {}
25489eb861aSAxel Dörfler void BArchivable::_ReservedArchivable2() {}
25589eb861aSAxel Dörfler void BArchivable::_ReservedArchivable3() {}
25689eb861aSAxel Dörfler 
25789eb861aSAxel Dörfler 
25889eb861aSAxel Dörfler // #pragma mark -
25989eb861aSAxel Dörfler 
26089eb861aSAxel Dörfler 
26189eb861aSAxel Dörfler BArchivable*
26289eb861aSAxel Dörfler instantiate_object(BMessage* archive, image_id* _id)
26389eb861aSAxel Dörfler {
26489eb861aSAxel Dörfler 	status_t statusBuffer;
26589eb861aSAxel Dörfler 	status_t* status = &statusBuffer;
26689eb861aSAxel Dörfler 	if (_id != NULL)
26789eb861aSAxel Dörfler 		status = _id;
26889eb861aSAxel Dörfler 
26989eb861aSAxel Dörfler 	// Check our params
27089eb861aSAxel Dörfler 	if (archive == NULL) {
27189eb861aSAxel Dörfler 		syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument");
27289eb861aSAxel Dörfler 		*status = B_BAD_VALUE;
27389eb861aSAxel Dörfler 		return NULL;
27489eb861aSAxel Dörfler 	}
27589eb861aSAxel Dörfler 
27689eb861aSAxel Dörfler 	// Get class name from archive
27789eb861aSAxel Dörfler 	const char* className = NULL;
27889eb861aSAxel Dörfler 	status_t err = archive->FindString(B_CLASS_FIELD, &className);
27989eb861aSAxel Dörfler 	if (err) {
28089eb861aSAxel Dörfler 		syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry "
28189eb861aSAxel Dörfler 			"defining the class name (%s).", strerror(err));
28289eb861aSAxel Dörfler 		*status = B_BAD_VALUE;
28389eb861aSAxel Dörfler 		return NULL;
28489eb861aSAxel Dörfler 	}
28589eb861aSAxel Dörfler 
28689eb861aSAxel Dörfler 	// Get sig from archive
28789eb861aSAxel Dörfler 	const char* signature = NULL;
28889eb861aSAxel Dörfler 	bool hasSignature = archive->FindString(B_ADD_ON_FIELD, &signature) == B_OK;
28989eb861aSAxel Dörfler 
29089eb861aSAxel Dörfler 	instantiation_func instantiationFunc = find_instantiation_func(className,
29189eb861aSAxel Dörfler 		signature);
29289eb861aSAxel Dörfler 
29389eb861aSAxel Dörfler 	// if find_instantiation_func() can't locate Class::Instantiate()
29489eb861aSAxel Dörfler 	// and a signature was specified
29589eb861aSAxel Dörfler 	if (!instantiationFunc && hasSignature) {
29689eb861aSAxel Dörfler 		// use BRoster::FindApp() to locate an app or add-on with the symbol
29789eb861aSAxel Dörfler 		BRoster Roster;
29889eb861aSAxel Dörfler 		entry_ref ref;
29989eb861aSAxel Dörfler 		err = Roster.FindApp(signature, &ref);
30089eb861aSAxel Dörfler 
30189eb861aSAxel Dörfler 		// if an entry_ref is obtained
30289eb861aSAxel Dörfler 		BEntry entry;
30389eb861aSAxel Dörfler 		if (err == B_OK)
30489eb861aSAxel Dörfler 			err = entry.SetTo(&ref);
30589eb861aSAxel Dörfler 
30689eb861aSAxel Dörfler 		BPath path;
30789eb861aSAxel Dörfler 		if (err == B_OK)
30889eb861aSAxel Dörfler 			err = entry.GetPath(&path);
30989eb861aSAxel Dörfler 
31089eb861aSAxel Dörfler 		if (err != B_OK) {
31189eb861aSAxel Dörfler 			syslog(LOG_ERR, "instantiate_object failed: Error finding app "
31289eb861aSAxel Dörfler 				"with signature \"%s\" (%s)", signature, strerror(err));
31389eb861aSAxel Dörfler 			*status = err;
31489eb861aSAxel Dörfler 			return NULL;
31589eb861aSAxel Dörfler 		}
31689eb861aSAxel Dörfler 
31789eb861aSAxel Dörfler 		// load the app/add-on
31889eb861aSAxel Dörfler 		image_id addOn = load_add_on(path.Path());
31989eb861aSAxel Dörfler 		if (addOn < B_OK) {
32089eb861aSAxel Dörfler 			syslog(LOG_ERR, "instantiate_object failed: Could not load "
32189eb861aSAxel Dörfler 				"add-on %s: %s.", path.Path(), strerror(addOn));
32289eb861aSAxel Dörfler 			*status = addOn;
32389eb861aSAxel Dörfler 			return NULL;
32489eb861aSAxel Dörfler 		}
32589eb861aSAxel Dörfler 
32689eb861aSAxel Dörfler 		// Save the image_id
32789eb861aSAxel Dörfler 		if (_id != NULL)
32889eb861aSAxel Dörfler 			*_id = addOn;
32989eb861aSAxel Dörfler 
33089eb861aSAxel Dörfler 		BString name = className;
33189eb861aSAxel Dörfler 		for (int32 pass = 0; pass < 2; pass++) {
33289eb861aSAxel Dörfler 			BString funcName;
33389eb861aSAxel Dörfler 			build_function_name(name, funcName);
33489eb861aSAxel Dörfler 
33589eb861aSAxel Dörfler 			instantiationFunc = find_function_in_image(funcName, addOn, err);
33689eb861aSAxel Dörfler 			if (instantiationFunc != NULL)
33789eb861aSAxel Dörfler 				break;
33889eb861aSAxel Dörfler 
33989eb861aSAxel Dörfler 			// Check if we have a private class, and add the BPrivate namespace
34089eb861aSAxel Dörfler 			// (for backwards compatibility)
34189eb861aSAxel Dörfler 			if (!add_private_namespace(name))
34289eb861aSAxel Dörfler 				break;
34389eb861aSAxel Dörfler 		}
34489eb861aSAxel Dörfler 
34589eb861aSAxel Dörfler 		if (instantiationFunc == NULL) {
34689eb861aSAxel Dörfler 			syslog(LOG_ERR, "instantiate_object failed: Failed to find exported "
34789eb861aSAxel Dörfler 				"Instantiate static function for class %s.", className);
34889eb861aSAxel Dörfler 			*status = B_NAME_NOT_FOUND;
34989eb861aSAxel Dörfler 			return NULL;
35089eb861aSAxel Dörfler 		}
35189eb861aSAxel Dörfler 	} else if (instantiationFunc == NULL) {
35289eb861aSAxel Dörfler 		syslog(LOG_ERR, "instantiate_object failed: No signature specified "
35389eb861aSAxel Dörfler 			"in archive, looking for class \"%s\".", className);
35489eb861aSAxel Dörfler 		*status = B_NAME_NOT_FOUND;
35589eb861aSAxel Dörfler 		return NULL;
35689eb861aSAxel Dörfler 	}
35789eb861aSAxel Dörfler 
35889eb861aSAxel Dörfler 	// if Class::Instantiate(BMessage*) was found
35989eb861aSAxel Dörfler 	if (instantiationFunc != NULL) {
36089eb861aSAxel Dörfler 		// use to create and return an object instance
36189eb861aSAxel Dörfler 		return instantiationFunc(archive);
36289eb861aSAxel Dörfler 	}
36389eb861aSAxel Dörfler 
36489eb861aSAxel Dörfler 	return NULL;
36589eb861aSAxel Dörfler }
36689eb861aSAxel Dörfler 
36789eb861aSAxel Dörfler 
36889eb861aSAxel Dörfler BArchivable*
36989eb861aSAxel Dörfler instantiate_object(BMessage* from)
37089eb861aSAxel Dörfler {
37189eb861aSAxel Dörfler 	return instantiate_object(from, NULL);
37252a38012Sejakowatz }
3739ecf9d1cSIngo Weinhold 
3749ecf9d1cSIngo Weinhold 
3759ecf9d1cSIngo Weinhold bool
37689eb861aSAxel Dörfler validate_instantiation(BMessage* from, const char* className)
37752a38012Sejakowatz {
37889eb861aSAxel Dörfler 	// Make sure our params are kosher -- original skimped here =P
37989eb861aSAxel Dörfler 	if (!from) {
38089eb861aSAxel Dörfler 		errno = B_BAD_VALUE;
38189eb861aSAxel Dörfler 		return false;
38289eb861aSAxel Dörfler 	}
38389eb861aSAxel Dörfler 
384*13bbfe42SAxel Dörfler 	BString name = className;
385*13bbfe42SAxel Dörfler 	for (int32 pass = 0; pass < 2; pass++) {
386*13bbfe42SAxel Dörfler 		const char* archiveClassName;
387*13bbfe42SAxel Dörfler 		for (int32 index = 0; from->FindString(B_CLASS_FIELD, index,
388*13bbfe42SAxel Dörfler 				&archiveClassName) == B_OK; ++index) {
389*13bbfe42SAxel Dörfler 			if (name == archiveClassName)
39052a38012Sejakowatz 				return true;
39152a38012Sejakowatz 		}
39252a38012Sejakowatz 
393*13bbfe42SAxel Dörfler 		if (!add_private_namespace(name))
394*13bbfe42SAxel Dörfler 			break;
395*13bbfe42SAxel Dörfler 	}
396*13bbfe42SAxel Dörfler 
39789eb861aSAxel Dörfler 	errno = B_MISMATCHED_VALUES;
39889eb861aSAxel Dörfler 	syslog(LOG_ERR, "validate_instantiation failed on class %s.", className);
39952a38012Sejakowatz 
40052a38012Sejakowatz 	return false;
40152a38012Sejakowatz }
40252a38012Sejakowatz 
40389eb861aSAxel Dörfler 
40489eb861aSAxel Dörfler instantiation_func
40589eb861aSAxel Dörfler find_instantiation_func(const char* className, const char* signature)
40689eb861aSAxel Dörfler {
40789eb861aSAxel Dörfler 	if (className == NULL) {
40889eb861aSAxel Dörfler 		errno = B_BAD_VALUE;
40989eb861aSAxel Dörfler 		return NULL;
41052a38012Sejakowatz 	}
41152a38012Sejakowatz 
41289eb861aSAxel Dörfler 	thread_info threadInfo;
41389eb861aSAxel Dörfler 	status_t err = get_thread_info(find_thread(NULL), &threadInfo);
41489eb861aSAxel Dörfler 	if (err != B_OK) {
41589eb861aSAxel Dörfler 		errno = err;
41689eb861aSAxel Dörfler 		return NULL;
41789eb861aSAxel Dörfler 	}
41889eb861aSAxel Dörfler 
41989eb861aSAxel Dörfler 	instantiation_func instantiationFunc = NULL;
42089eb861aSAxel Dörfler 	image_info imageInfo;
42189eb861aSAxel Dörfler 
42289eb861aSAxel Dörfler 	BString name = className;
42389eb861aSAxel Dörfler 	for (int32 pass = 0; pass < 2; pass++) {
42489eb861aSAxel Dörfler 		BString funcName;
42589eb861aSAxel Dörfler 		build_function_name(name, funcName);
42689eb861aSAxel Dörfler 
42789eb861aSAxel Dörfler 		// for each image_id in team_id
42889eb861aSAxel Dörfler 		int32 cookie = 0;
42989eb861aSAxel Dörfler 		while (instantiationFunc == NULL
43089eb861aSAxel Dörfler 			&& get_next_image_info(threadInfo.team, &cookie, &imageInfo)
43189eb861aSAxel Dörfler 				== B_OK) {
43289eb861aSAxel Dörfler 			instantiationFunc = find_function_in_image(funcName, imageInfo.id,
43389eb861aSAxel Dörfler 				err);
43489eb861aSAxel Dörfler 		}
43589eb861aSAxel Dörfler 		if (instantiationFunc != NULL)
43689eb861aSAxel Dörfler 			break;
43789eb861aSAxel Dörfler 
43889eb861aSAxel Dörfler 		// Check if we have a private class, and add the BPrivate namespace
43989eb861aSAxel Dörfler 		// (for backwards compatibility)
44089eb861aSAxel Dörfler 		if (!add_private_namespace(name))
44189eb861aSAxel Dörfler 			break;
44289eb861aSAxel Dörfler 	}
44389eb861aSAxel Dörfler 
44489eb861aSAxel Dörfler 	if (instantiationFunc != NULL
44589eb861aSAxel Dörfler 		&& check_signature(signature, imageInfo) != B_OK)
44689eb861aSAxel Dörfler 		return NULL;
44789eb861aSAxel Dörfler 
44889eb861aSAxel Dörfler 	return instantiationFunc;
44989eb861aSAxel Dörfler }
45089eb861aSAxel Dörfler 
45189eb861aSAxel Dörfler 
45289eb861aSAxel Dörfler instantiation_func
45389eb861aSAxel Dörfler find_instantiation_func(const char* className)
45489eb861aSAxel Dörfler {
45589eb861aSAxel Dörfler 	return find_instantiation_func(className, NULL);
45689eb861aSAxel Dörfler }
45789eb861aSAxel Dörfler 
45889eb861aSAxel Dörfler 
45989eb861aSAxel Dörfler instantiation_func
46089eb861aSAxel Dörfler find_instantiation_func(BMessage* archive)
46189eb861aSAxel Dörfler {
46289eb861aSAxel Dörfler 	if (archive == NULL) {
46389eb861aSAxel Dörfler 		errno = B_BAD_VALUE;
46489eb861aSAxel Dörfler 		return NULL;
46589eb861aSAxel Dörfler 	}
46689eb861aSAxel Dörfler 
46789eb861aSAxel Dörfler 	const char* name = NULL;
46889eb861aSAxel Dörfler 	const char* signature = NULL;
46989eb861aSAxel Dörfler 	if (archive->FindString(B_CLASS_FIELD, &name) != B_OK
47089eb861aSAxel Dörfler 		|| archive->FindString(B_ADD_ON_FIELD, &signature)) {
47189eb861aSAxel Dörfler 		errno = B_BAD_VALUE;
47289eb861aSAxel Dörfler 		return NULL;
47389eb861aSAxel Dörfler 	}
47489eb861aSAxel Dörfler 
47589eb861aSAxel Dörfler 	return find_instantiation_func(name, signature);
47652a38012Sejakowatz }
47752a38012Sejakowatz 
478