summaryrefslogtreecommitdiff
path: root/src/vm/crossgenroresolvenamespace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/crossgenroresolvenamespace.cpp')
-rw-r--r--src/vm/crossgenroresolvenamespace.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/vm/crossgenroresolvenamespace.cpp b/src/vm/crossgenroresolvenamespace.cpp
new file mode 100644
index 0000000000..3ddd8f72a3
--- /dev/null
+++ b/src/vm/crossgenroresolvenamespace.cpp
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//+----------------------------------------------------------------------------
+//
+
+//
+// Adapted from Windows sources. Modified to run on Windows version < Win8, so
+// that we can use this in CrossGen.
+//
+
+//
+//-----------------------------------------------------------------------------
+
+#include "common.h"
+#include "crossgenroresolvenamespace.h"
+#include "stringarraylist.h"
+
+namespace Crossgen
+{
+
+#define WINDOWS_NAMESPACE W("Windows")
+#define WINDOWS_NAMESPACE_PREFIX WINDOWS_NAMESPACE W(".")
+#define WINMD_FILE_EXTENSION_L W(".winmd")
+
+StringArrayList* g_wszWindowsNamespaceDirectories;
+StringArrayList* g_wszUserNamespaceDirectories;
+
+BOOL
+IsWindowsNamespace(const WCHAR * wszNamespace)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ if (wcsncmp(wszNamespace, WINDOWS_NAMESPACE_PREFIX, (_countof(WINDOWS_NAMESPACE_PREFIX) - 1)) == 0)
+ {
+ return TRUE;
+ }
+ else if (wcscmp(wszNamespace, WINDOWS_NAMESPACE) == 0)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+DoesFileExist(
+ const WCHAR * wszFileName)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ BOOL fFileExists = TRUE;
+ DWORD dwFileAttributes;
+ dwFileAttributes = GetFileAttributesW(wszFileName);
+
+ if ((dwFileAttributes == INVALID_FILE_ATTRIBUTES) ||
+ (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ fFileExists = FALSE;
+ }
+
+ return fFileExists;
+}
+
+
+HRESULT
+FindNamespaceFileInDirectory(
+ const WCHAR * wszNamespace,
+ const WCHAR * wszDirectory,
+ DWORD * pcMetadataFiles,
+ SString ** ppMetadataFiles)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ if (wszDirectory == nullptr)
+ return ERROR_NOT_SUPPORTED;
+
+ WCHAR wszFilePath[MAX_LONGPATH + 1];
+ wcscpy_s(
+ wszFilePath,
+ _countof(wszFilePath),
+ wszDirectory);
+
+ WCHAR * wszFirstFileNameChar = wszFilePath + wcslen(wszFilePath);
+
+ // If there's no backslash, add one.
+ if (*(wszFirstFileNameChar - 1) != '\\')
+ *wszFirstFileNameChar++ = '\\';
+
+ WCHAR wszRemainingNamespace[MAX_PATH_FNAME +1];
+ wcscpy_s(
+ wszRemainingNamespace,
+ _countof(wszRemainingNamespace),
+ wszNamespace);
+
+ do
+ {
+ *wszFirstFileNameChar = W('\0');
+ wcscat_s(
+ wszFilePath,
+ _countof(wszFilePath),
+ wszRemainingNamespace);
+ wcscat_s(
+ wszFilePath,
+ _countof(wszFilePath),
+ WINMD_FILE_EXTENSION_L);
+
+ if (DoesFileExist(wszFilePath))
+ {
+ *ppMetadataFiles = new SString(wszFilePath);
+ *pcMetadataFiles = 1;
+ return S_OK;
+ }
+
+ WCHAR * wszLastDotChar = wcsrchr(wszRemainingNamespace, W('.'));
+ if (wszLastDotChar == nullptr)
+ {
+ *ppMetadataFiles = nullptr;
+ *pcMetadataFiles = 0;
+ return S_FALSE;
+ }
+ *wszLastDotChar = W('\0');
+ } while (true);
+}
+
+
+__checkReturn
+HRESULT WINAPI CrossgenRoResolveNamespace(
+ const LPCWSTR wszNamespace,
+ DWORD * pcMetadataFiles,
+ SString ** ppMetadataFiles)
+{
+ LIMITED_METHOD_CONTRACT;
+ HRESULT hr = S_OK;
+
+ if (IsWindowsNamespace(wszNamespace))
+ {
+ DWORD cAppPaths = g_wszWindowsNamespaceDirectories->GetCount();
+
+ for (DWORD i = 0; i < cAppPaths; i++)
+ {
+ // Returns S_FALSE on file not found so we continue proving app directory graph
+ IfFailRet(FindNamespaceFileInDirectory(
+ wszNamespace,
+ g_wszWindowsNamespaceDirectories->Get(i).GetUnicode(),
+ pcMetadataFiles,
+ ppMetadataFiles));
+
+ if (hr == S_OK)
+ {
+ return hr;
+ }
+ }
+ }
+ else
+ {
+ DWORD cAppPaths = g_wszUserNamespaceDirectories->GetCount();
+
+ for (DWORD i = 0; i < cAppPaths; i++)
+ {
+ // Returns S_FALSE on file not found so we continue proving app directory graph
+ IfFailRet(FindNamespaceFileInDirectory(
+ wszNamespace,
+ g_wszUserNamespaceDirectories->Get(i).GetUnicode(),
+ pcMetadataFiles,
+ ppMetadataFiles));
+
+ if (hr == S_OK)
+ {
+ return hr;
+ }
+ }
+ }
+
+ return hr;
+} // RoResolveNamespace
+
+void SetFirstPartyWinMDPaths(StringArrayList* saAppPaths)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ g_wszWindowsNamespaceDirectories = saAppPaths;
+}
+
+void SetAppPaths(StringArrayList* saAppPaths)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ g_wszUserNamespaceDirectories = saAppPaths;
+}
+
+}// Namespace Crossgen