summaryrefslogtreecommitdiff
path: root/src/binder/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/binder/utils.cpp')
-rw-r--r--src/binder/utils.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/binder/utils.cpp b/src/binder/utils.cpp
new file mode 100644
index 0000000000..3069802700
--- /dev/null
+++ b/src/binder/utils.cpp
@@ -0,0 +1,352 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// ============================================================
+//
+// Utils.cpp
+//
+
+
+//
+// Implements a bunch of binder auxilary functions
+//
+// ============================================================
+
+#define DISABLE_BINDER_DEBUG_LOGGING
+
+#include "utils.hpp"
+
+#include <shlwapi.h>
+
+#include "strongname.h"
+#include "corpriv.h"
+
+namespace BINDER_SPACE
+{
+ namespace
+ {
+ inline BOOL IsPathSeparator(WCHAR wcChar)
+ {
+ // Invariant: Valid only for MutateUrlToPath treated pathes
+ return (wcChar == W('\\'));
+ }
+
+ inline const WCHAR *GetPlatformPathSeparator()
+ {
+#ifdef PLATFORM_UNIX
+ return W("/");
+#else
+ return W("\\");
+#endif // PLATFORM_UNIX
+ }
+
+ inline WCHAR ToPlatformPathSepator(WCHAR wcChar)
+ {
+#ifdef PLATFORM_UNIX
+ if (IsPathSeparator(wcChar))
+ {
+ wcChar = W('/');
+ }
+#endif // PLATFORM_UNIX
+
+ return wcChar;
+ }
+
+ inline BOOL IsDoublePathSeparator(SString::CIterator &cur)
+ {
+ return (IsPathSeparator(cur[0]) && IsPathSeparator(cur[1]));
+ }
+
+ bool NeedToRemoveDoubleAndNormalizePathSeparators(SString const &path)
+ {
+#ifdef PLATFORM_UNIX
+ return true;
+#else
+ SString::CIterator begin = path.Begin();
+ SString::CIterator end = path.End();
+ SString::CIterator cur = path.Begin();
+
+ while (cur < end)
+ {
+ if ((cur != begin) && ((cur + 2) < end) && IsDoublePathSeparator(cur))
+ {
+ return true;
+ }
+
+ cur++;
+ }
+
+ return false;
+#endif
+ }
+
+ void RemoveDoubleAndNormalizePathSeparators(SString &path)
+ {
+ BINDER_LOG_ENTER(W("Utils::RemoveDoubleAndNormalizePathSeparators"));
+
+ SString::Iterator begin = path.Begin();
+ SString::Iterator end = path.End();
+ SString::Iterator cur = path.Begin();
+ PathString resultPath;
+
+ BINDER_LOG_STRING(W("path"), path);
+
+ while (cur < end)
+ {
+ if ((cur != begin) && ((cur + 2) < end) && IsDoublePathSeparator(cur))
+ {
+ // Skip the doublette
+ cur++;
+ }
+
+ resultPath.Append(ToPlatformPathSepator(cur[0]));
+ cur++;
+ }
+
+ BINDER_LOG_STRING(W("resultPath"), resultPath);
+
+ path.Set(resultPath);
+
+ BINDER_LOG_LEAVE(W("Utils::RemoveDoubleAndNormalizePathSeparators"));
+ }
+ }
+
+ HRESULT FileOrDirectoryExists(PathString &path)
+ {
+ HRESULT hr = S_FALSE;
+
+ DWORD dwFileAttributes = WszGetFileAttributes(path.GetUnicode());
+ if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ hr = HRESULT_FROM_GetLastError();
+
+ if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
+ (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)))
+ {
+ hr = S_FALSE;
+ }
+ }
+ else
+ {
+ hr = S_TRUE;
+ }
+
+ return hr;
+ }
+
+ HRESULT FileOrDirectoryExistsLog(PathString &path)
+ {
+ HRESULT hr = S_FALSE;
+ BINDER_LOG_ENTER(W("Utils::FileOrDirectoryExistsLog"));
+ BINDER_LOG_STRING(W("path"), path);
+
+ hr = FileOrDirectoryExists(path);
+
+ BINDER_LOG_LEAVE_HR(W("Utils::FileOrDirectoryExistsLog"), hr);
+ return hr;
+ }
+
+ BOOL IsURL(SString &urlOrPath)
+ {
+ // This is also in defined rotor pal
+ return PathIsURLW(urlOrPath);
+ }
+
+ void MutateUrlToPath(SString &urlOrPath)
+ {
+ BINDER_LOG_ENTER(W("Utils::MutateUrlToPath"));
+ const SString fileUrlPrefix(SString::Literal, W("file://"));
+ SString::Iterator i = urlOrPath.Begin();
+
+ BINDER_LOG_STRING(W("URL"), urlOrPath);
+
+ if (urlOrPath.MatchCaseInsensitive(i, fileUrlPrefix))
+ {
+ urlOrPath.Delete(i, fileUrlPrefix.GetCount());
+
+ i = urlOrPath.Begin() + 1;
+ if (i[0] == W(':'))
+ {
+ // CLR erroneously passes in file:// prepended to file paths,
+ // so we can't tell the difference between UNC and local file.
+ goto Exit;
+ }
+
+ i = urlOrPath.Begin();
+#if !defined(PLATFORM_UNIX)
+ if (i[0] == W('/'))
+ {
+ // Disk path file:///
+ urlOrPath.Delete(i, 1);
+ }
+ else if (i[0] != W('\\'))
+ {
+ // UNC Path, re-insert "//" if not the wrong file://\\...
+ urlOrPath.Insert(i, W("//"));
+ }
+#else
+ // Unix doesn't have a distinction between local and network path
+ _ASSERTE(i[0] == W('\\') || i[0] == W('/'));
+#endif
+ }
+
+ Exit:
+ while (urlOrPath.Find(i, W('/')))
+ {
+ urlOrPath.Replace(i, W('\\'));
+ }
+
+ BINDER_LOG_STRING(W("Path"), urlOrPath);
+ BINDER_LOG_LEAVE(W("Utils::MutateUrlToPath"));
+ }
+
+ void MutatePathToUrl(SString &pathOrUrl)
+ {
+ BINDER_LOG_ENTER(W("Utils::MutatePathToUrl"));
+ SString::Iterator i = pathOrUrl.Begin();
+
+ BINDER_LOG_STRING(W("Path"), pathOrUrl);
+
+#if !defined(PLATFORM_UNIX)
+ // Network path \\server --> file://server
+ // Disk path c:\dir --> file:///c:/dir
+ if (i[0] == W('\\'))
+ {
+ const SString networkUrlPrefix(SString::Literal, W("file:"));
+
+ // Network path
+ pathOrUrl.Insert(i, networkUrlPrefix);
+ pathOrUrl.Skip(i, networkUrlPrefix);
+ }
+ else
+ {
+ const SString diskPathUrlPrefix(SString::Literal, W("file:///"));
+
+ // Disk path
+ pathOrUrl.Insert(i, diskPathUrlPrefix);
+ pathOrUrl.Skip(i, diskPathUrlPrefix);
+ }
+#else
+ // Unix doesn't have a distinction between a network or a local path
+ _ASSERTE(i[0] == W('\\') || i[0] == W('/'));
+ const SString fileUrlPrefix(SString::Literal, W("file://"));
+
+ pathOrUrl.Insert(i, fileUrlPrefix);
+ pathOrUrl.Skip(i, fileUrlPrefix);
+#endif
+
+ while (pathOrUrl.Find(i, W('\\')))
+ {
+ pathOrUrl.Replace(i, W('/'));
+ }
+
+ BINDER_LOG_STRING(W("URL"), pathOrUrl);
+ BINDER_LOG_LEAVE(W("Utils::MutatePathToUrl"));
+ }
+
+ void PlatformPath(SString &path)
+ {
+ BINDER_LOG_ENTER(W("Utils::PlatformPath"));
+ BINDER_LOG_STRING(W("input path"), path);
+
+ // Create platform representation
+ MutateUrlToPath(path);
+ if (NeedToRemoveDoubleAndNormalizePathSeparators(path))
+ RemoveDoubleAndNormalizePathSeparators(path);
+
+ BINDER_LOG_STRING(W("platform path"), path);
+
+ BINDER_LOG_LEAVE(W("Utils::PlatformPath"));
+ }
+
+ void CanonicalizePath(SString &path, BOOL fAppendPathSeparator)
+ {
+ BINDER_LOG_ENTER(W("Utils::CanonicalizePath"));
+ BINDER_LOG_STRING(W("input path"), path);
+
+ if (!path.IsEmpty())
+ {
+ WCHAR wszCanonicalPath[MAX_PATH];
+ PlatformPath(path);
+
+ // This is also defined in rotor pal
+ if (PathCanonicalizeW(wszCanonicalPath, path))
+ {
+ path.Set(wszCanonicalPath);
+ }
+
+ if (fAppendPathSeparator)
+ {
+ SString platformPathSeparator(SString::Literal, GetPlatformPathSeparator());
+
+ if (!path.EndsWith(platformPathSeparator))
+ {
+ path.Append(platformPathSeparator);
+ }
+ }
+ }
+
+ BINDER_LOG_STRING(W("canonicalized path"), path);
+ BINDER_LOG_LEAVE(W("Utils::CanonicalizePath"));
+ }
+
+ void CombinePath(SString &pathA,
+ SString &pathB,
+ SString &combinedPath)
+ {
+ BINDER_LOG_ENTER(W("Utils::CombinePath"));
+
+ BINDER_LOG_STRING(W("path A"), pathA);
+ BINDER_LOG_STRING(W("path B"), pathB);
+
+ WCHAR tempResultPath[MAX_PATH];
+ if (PathCombineW(tempResultPath, pathA, pathB))
+ {
+ combinedPath.Set(tempResultPath);
+ BINDER_LOG_STRING(W("combined path"), tempResultPath);
+ }
+ else
+ {
+ combinedPath.Clear();
+ }
+
+ BINDER_LOG_LEAVE(W("Utils::CombinePath"));
+ }
+
+ HRESULT GetTokenFromPublicKey(SBuffer &publicKeyBLOB,
+ SBuffer &publicKeyTokenBLOB)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(W("GetTokenFromPublicKey"));
+
+ const BYTE *pByteKey = publicKeyBLOB;
+ DWORD dwKeyLen = publicKeyBLOB.GetSize();
+ BYTE *pByteToken = NULL;
+ DWORD dwTokenLen = 0;
+
+ if (!StrongNameTokenFromPublicKey(const_cast<BYTE *>(pByteKey),
+ dwKeyLen,
+ &pByteToken,
+ &dwTokenLen))
+ {
+ BINDER_LOG(W("StrongNameTokenFromPublicKey failed!"));
+ IF_FAIL_GO(StrongNameErrorInfo());
+ }
+ else
+ {
+ _ASSERTE(pByteToken != NULL);
+ publicKeyTokenBLOB.Set(pByteToken, dwTokenLen);
+ StrongNameFreeBuffer(pByteToken);
+ }
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(W("GetTokenFromPublicKey"), hr);
+ return hr;
+ }
+
+ BOOL IsFileNotFound(HRESULT hr)
+ {
+ return RuntimeFileNotFound(hr);
+ }
+};