}
#ifdef FEATURE_PAL
-static void DetermineLibNameVariations(const WCHAR* const** libNameVariations, int* numberOfVariations, const SString& libName, bool libNameIsRelativePath)
+static const int MaxVariationCount = 4;
+static void DetermineLibNameVariations(const WCHAR** libNameVariations, int* numberOfVariations, const SString& libName, bool libNameIsRelativePath)
{
- if (libNameIsRelativePath)
+ // Supported lib name variations
+ static auto NameFmt = W("%.0s%s%.0s");
+ static auto PrefixNameFmt = W("%s%s%.0s");
+ static auto NameSuffixFmt = W("%.0s%s%s");
+ static auto PrefixNameSuffixFmt = W("%s%s%s");
+
+ _ASSERTE(*numberOfVariations >= MaxVariationCount);
+
+ int varCount = 0;
+ if (!libNameIsRelativePath)
+ {
+ libNameVariations[varCount++] = NameFmt;
+ }
+ else
{
// We check if the suffix is contained in the name, because on Linux it is common to append
// a version number to the library name (e.g. 'libicuuc.so.57').
- bool containsSuffix;
+ bool containsSuffix = false;
SString::CIterator it = libName.Begin();
if (libName.Find(it, PLATFORM_SHARED_LIB_SUFFIX_W))
{
- it += wcslen(PLATFORM_SHARED_LIB_SUFFIX_W);
+ it += COUNTOF(PLATFORM_SHARED_LIB_SUFFIX_W);
containsSuffix = it == libName.End() || *it == (WCHAR)'.';
}
- else
- {
- containsSuffix = false;
- }
+
+ // If the path contains a path delimiter, we don't add a prefix
+ it = libName.Begin();
+ bool containsDelim = libName.Find(it, DIRECTORY_SEPARATOR_STR_W);
if (containsSuffix)
{
- static const WCHAR* const SuffixLast[] =
- {
- W("%.0s%s"), // name
- W("%s%s%.0s"), // prefix+name
- W("%.0s%s%s"), // name+suffix
- W("%s%s%s") // prefix+name+suffix
- };
- *libNameVariations = SuffixLast;
- *numberOfVariations = COUNTOF(SuffixLast);
+ libNameVariations[varCount++] = NameFmt;
+
+ if (!containsDelim)
+ libNameVariations[varCount++] = PrefixNameFmt;
+
+ libNameVariations[varCount++] = NameSuffixFmt;
+
+ if (!containsDelim)
+ libNameVariations[varCount++] = PrefixNameSuffixFmt;
}
else
{
- static const WCHAR* const SuffixFirst[] =
- {
- W("%.0s%s%s"), // name+suffix
- W("%s%s%s"), // prefix+name+suffix
- W("%.0s%s"), // name
- W("%s%s%.0s") // prefix+name
- };
- *libNameVariations = SuffixFirst;
- *numberOfVariations = COUNTOF(SuffixFirst);
+ libNameVariations[varCount++] = NameSuffixFmt;
+
+ if (!containsDelim)
+ libNameVariations[varCount++] = PrefixNameSuffixFmt;
+
+ libNameVariations[varCount++] = NameFmt;
+
+ if (!containsDelim)
+ libNameVariations[varCount++] = PrefixNameFmt;
}
}
- else
- {
- static const WCHAR* const NameOnly[] =
- {
- W("%.0s%s")
- };
- *libNameVariations = NameOnly;
- *numberOfVariations = COUNTOF(NameOnly);
- }
+
+ *numberOfVariations = varCount;
}
#else // FEATURE_PAL
-static void DetermineLibNameVariations(const WCHAR* const** libNameVariations, int* numberOfVariations, const SString& libName, bool libNameIsRelativePath)
+static const int MaxVariationCount = 2;
+static void DetermineLibNameVariations(const WCHAR** libNameVariations, int* numberOfVariations, const SString& libName, bool libNameIsRelativePath)
{
+ // Supported lib name variations
+ static auto NameFmt = W("%.0s%s%.0s");
+ static auto NameSuffixFmt = W("%.0s%s%s");
+
+ _ASSERTE(*numberOfVariations >= MaxVariationCount);
+
+ int varCount = 0;
+
// The purpose of following code is to workaround LoadLibrary limitation:
// LoadLibrary won't append extension if filename itself contains '.'. Thus it will break the following scenario:
// [DllImport("A.B")] // The full name for file is "A.B.dll". This is common code pattern for cross-platform PInvoke
// If the string specifies a full path, the function searches only that path for the module.
// If the string specifies a module name without a path and the file name extension is omitted, the function appends the default library extension .dll to the module name.
// To prevent the function from appending .dll to the module name, include a trailing point character (.) in the module name string.
- static const WCHAR* const NameOnly[] =
- {
- W("%.0s%s")
- };
- *libNameVariations = NameOnly;
- *numberOfVariations = COUNTOF(NameOnly);
+ libNameVariations[varCount++] = NameFmt;
}
else
{
- static const WCHAR* const SuffixLast[] =
- {
- W("%.0s%s"), // name
- W("%.0s%s%s"), // name+suffix
- };
- *libNameVariations = SuffixLast;
- *numberOfVariations = COUNTOF(SuffixLast);
+ libNameVariations[varCount++] = NameFmt;
+ libNameVariations[varCount++] = NameSuffixFmt;
}
+
+ *numberOfVariations = varCount;
}
#endif // FEATURE_PAL
// even if it has one, or to leave off a prefix like "lib" even if it has one
// (both of these are typically done to smooth over cross-platform differences).
// We try to dlopen with such variations on the original.
- const WCHAR* const* prefixSuffixCombinations = nullptr;
- int numberOfVariations = 0;
- DetermineLibNameVariations(&prefixSuffixCombinations, &numberOfVariations, wszLibName, libNameIsRelativePath);
+ const WCHAR* prefixSuffixCombinations[MaxVariationCount] = {};
+ int numberOfVariations = COUNTOF(prefixSuffixCombinations);
+ DetermineLibNameVariations(prefixSuffixCombinations, &numberOfVariations, wszLibName, libNameIsRelativePath);
for (int i = 0; hmod == NULL && i < numberOfVariations; i++)
{
SString currLibNameVariation;
currLibNameVariation.Printf(prefixSuffixCombinations[i], PLATFORM_SHARED_LIB_PREFIX_W, wszLibName, PLATFORM_SHARED_LIB_SUFFIX_W);
- if (hmod == NULL)
- {
- // NATIVE_DLL_SEARCH_DIRECTORIES set by host is considered well known path
- hmod = LoadFromNativeDllSearchDirectories(pDomain, currLibNameVariation, loadWithAlteredPathFlags, pErrorTracker);
- }
+
+ // NATIVE_DLL_SEARCH_DIRECTORIES set by host is considered well known path
+ hmod = LoadFromNativeDllSearchDirectories(pDomain, currLibNameVariation, loadWithAlteredPathFlags, pErrorTracker);
BOOL searchAssemblyDirectory = TRUE;
if (hmod == NULL)