diff options
Diffstat (limited to 'src/vm/crossgenroresolvenamespace.cpp')
-rw-r--r-- | src/vm/crossgenroresolvenamespace.cpp | 194 |
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 |