summaryrefslogtreecommitdiff
path: root/src/inc/clr
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/clr')
-rw-r--r--src/inc/clr/fs.h16
-rw-r--r--src/inc/clr/fs/dir.h129
-rw-r--r--src/inc/clr/fs/file.h40
-rw-r--r--src/inc/clr/fs/path.h141
-rw-r--r--src/inc/clr/stack.h99
-rw-r--r--src/inc/clr/str.h28
-rw-r--r--src/inc/clr/win32.h38
7 files changed, 491 insertions, 0 deletions
diff --git a/src/inc/clr/fs.h b/src/inc/clr/fs.h
new file mode 100644
index 0000000000..d6bcb75309
--- /dev/null
+++ b/src/inc/clr/fs.h
@@ -0,0 +1,16 @@
+// 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.
+//
+
+//
+// This header will include all headers relating to file system functionality.
+
+#ifndef _clr_fs_h_
+#define _clr_fs_h_
+
+#include "fs/path.h"
+#include "fs/file.h"
+#include "fs/dir.h"
+
+#endif // _clr_fs_h_
diff --git a/src/inc/clr/fs/dir.h b/src/inc/clr/fs/dir.h
new file mode 100644
index 0000000000..2516151a55
--- /dev/null
+++ b/src/inc/clr/fs/dir.h
@@ -0,0 +1,129 @@
+// 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.
+//
+
+//
+// This header provides general directory-related file system services.
+
+#ifndef _clr_fs_Dir_h_
+#define _clr_fs_Dir_h_
+
+#include "clrtypes.h"
+#include "clr/str.h"
+#include "strsafe.h"
+
+#ifndef countof
+ #define countof(x) (sizeof(x) / sizeof(x[0]))
+#endif // !countof
+
+namespace clr
+{
+ namespace fs
+ {
+ class Dir
+ {
+ public:
+ static inline bool Exists(
+ LPCWSTR wzDirPath)
+ {
+ DWORD attrs = WszGetFileAttributes(wzDirPath);
+ return (attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_DIRECTORY);
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Creates new directory indicated by wzDirPath.
+ //
+ // Returns:
+ // S_OK - on success directory creation
+ // S_FALSE - when directory previously existed
+ // HR(ERROR_PATH_NOT_FOUND) - when creation of dir fails.
+ static inline HRESULT Create(
+ LPCWSTR wzDirPath)
+ {
+ HRESULT hr = S_OK;
+
+ if (!WszCreateDirectory(wzDirPath, nullptr))
+ {
+ hr = HRESULT_FROM_GetLastError();
+ if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
+ {
+ hr = S_FALSE;
+ }
+ }
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Creates the specified directory and all required subdirectories. wzDirPath will be
+ // temporarily modified in the process.
+ //
+ // Returns:
+ // S_OK - on success directory creation
+ // S_FALSE - when directory previously existed
+ // HR(ERROR_PATH_NOT_FOUND) - when creation of any dir fails.
+ static inline HRESULT CreateRecursively(
+ __inout_z LPWSTR wzDirPath,
+ size_t cchDirPath = 0)
+ {
+ HRESULT hr = S_OK;
+
+ if (wzDirPath == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ if (cchDirPath == 0)
+ {
+ cchDirPath = wcslen(wzDirPath);
+ }
+
+ // Try to create the path. If it fails, assume that's because the parent folder does
+ // not exist. Try to create the parent then re-attempt.
+ WCHAR chOrig = wzDirPath[cchDirPath];
+ hr = Create(wzDirPath);
+ if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
+ {
+ for (WCHAR* pCurCh = wzDirPath + cchDirPath - 1; pCurCh != wzDirPath; --pCurCh)
+ {
+ if (*pCurCh == W('\\') || *pCurCh == W('\0'))
+ {
+ WCHAR chOrig = *pCurCh;
+ *pCurCh = W('\0');
+ IfFailRet(CreateRecursively(wzDirPath, pCurCh - wzDirPath));
+ *pCurCh = chOrig;
+ break;
+ }
+ }
+ IfFailRet(Create(wzDirPath));
+ }
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Creates the specified directory and all required subdirectories.
+ static inline HRESULT CreateRecursively(
+ LPCWSTR wzDirPath)
+ {
+ HRESULT hr = S_OK;
+
+ if (wzDirPath == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ // Make a writable copy of wzDirPath
+ size_t cchDirPath = wcslen(wzDirPath);
+ CQuickWSTR wzBuffer;
+ IfFailRet(wzBuffer.ReSizeNoThrow(cchDirPath + 1));
+ wcscpy_s(wzBuffer.Ptr(), wzBuffer.Size(), wzDirPath);
+ IfFailRet(CreateRecursively(wzBuffer.Ptr(), cchDirPath));
+
+ return hr;
+ }
+ };
+ }
+}
+
+#endif // _clr_fs_Dir_h_
diff --git a/src/inc/clr/fs/file.h b/src/inc/clr/fs/file.h
new file mode 100644
index 0000000000..70f22a29fa
--- /dev/null
+++ b/src/inc/clr/fs/file.h
@@ -0,0 +1,40 @@
+// 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.
+//
+
+//
+// This header provides general filename-related file system services.
+
+#ifndef _clr_fs_File_h_
+#define _clr_fs_File_h_
+
+#include "clrtypes.h"
+#include "cor.h" // SELECTANY
+
+namespace clr
+{
+ namespace fs
+ {
+ // This list taken from ndp/clr/src/bcl/system/io/path.cs
+ SELECTANY WCHAR const g_rgInvalidFileNameChars[] =
+ { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6,
+ (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14,
+ (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22,
+ (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30,
+ (WCHAR)31, W(':'), W('*'), W('?'), W('\\'), W('/') };
+
+ class File
+ {
+ public:
+ static inline bool Exists(
+ LPCWSTR wzFilePath)
+ {
+ DWORD attrs = WszGetFileAttributes(wzFilePath);
+ return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY);
+ }
+ };
+ }
+}
+
+#endif // _clr_fs_File_h_
diff --git a/src/inc/clr/fs/path.h b/src/inc/clr/fs/path.h
new file mode 100644
index 0000000000..7c1995ecb2
--- /dev/null
+++ b/src/inc/clr/fs/path.h
@@ -0,0 +1,141 @@
+// 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.
+//
+
+//
+// This header provides general path-related file system services.
+
+#ifndef _clr_fs_Path_h_
+#define _clr_fs_Path_h_
+
+#include "clrtypes.h"
+#include "cor.h" // SELECTANY
+
+#include "strsafe.h"
+
+#include "clr/str.h"
+
+#ifndef LONG_FORMAT_PATH_PREFIX
+ #define LONG_FORMAT_PATH_PREFIX W("\\\\?\\")
+#endif
+
+namespace clr
+{
+ namespace fs
+ {
+ // This list taken from ndp/clr/src/bcl/system/io/path.cs
+ SELECTANY WCHAR const g_rgInvalidPathChars[] =
+ { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6,
+ (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14,
+ (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22,
+ (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30,
+ (WCHAR)31 };
+
+ class Path
+ {
+ public:
+ //-----------------------------------------------------------------------------------------
+ static inline bool
+ Exists(
+ LPCWSTR wzPath)
+ {
+ DWORD attrs = WszGetFileAttributes(wzPath);
+ return (attrs != INVALID_FILE_ATTRIBUTES);
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Returns true if wzPath represents a long format path (i.e., prefixed with '\\?\').
+ static inline bool
+ HasLongFormatPrefix(LPCWSTR wzPath)
+ {
+ _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
+ return wcscmp(wzPath, LONG_FORMAT_PATH_PREFIX) == 0;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Returns true if wzPath represents a relative path.
+ static inline bool
+ IsRelative(LPCWSTR wzPath)
+ {
+ _ASSERTE(wzPath != nullptr);
+
+ // Similar to System.IO.Path.IsRelative()
+#if PLATFORM_UNIX
+ if(wzPath[0] == VOLUME_SEPARATOR_CHAR_W)
+ {
+ return false;
+ }
+#else
+ // Check for a paths like "C:\..." or "\\...". Additional notes:
+ // - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix
+ // - "\..." - these paths are relative, as they depend on the current drive
+ // - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C
+ if (wzPath[0] != W('\0') &&
+ wzPath[1] == VOLUME_SEPARATOR_CHAR_W &&
+ wzPath[2] == DIRECTORY_SEPARATOR_CHAR_W &&
+ (
+ (wzPath[0] >= W('A') && wzPath[0] <= W('Z')) ||
+ (wzPath[0] >= W('a') && wzPath[0] <= W('z'))
+ ))
+ {
+ return false;
+ }
+ if (wzPath[0] == DIRECTORY_SEPARATOR_CHAR_W && wzPath[1] == DIRECTORY_SEPARATOR_CHAR_W)
+ {
+ return false;
+ }
+#endif
+
+ return true;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Combines two path parts. wzPathLeft must be a directory path and may be either absolute
+ // or relative. wzPathRight may be a directory or file path and must be relative. The
+ // result is placed in wzBuffer and the number of chars written is placed in pcchBuffer on
+ // success; otherwise an error HRESULT is returned.
+ static HRESULT
+ Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __in DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer)
+ {
+ STATIC_CONTRACT_NOTHROW;
+
+ HRESULT hr = S_OK;
+
+ if (clr::str::IsNullOrEmpty(wzPathLeft) || clr::str::IsNullOrEmpty(wzPathRight) || pcchBuffer == nullptr)
+ return E_INVALIDARG;
+
+ LPWSTR wzBuf = wzBuffer;
+ size_t cchBuf = *pcchBuffer;
+
+ IfFailRet(StringCchCopyExW(wzBuf, cchBuf, wzPathLeft, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
+ IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == DIRECTORY_SEPARATOR_CHAR_W ? W("") : DIRECTORY_SEPARATOR_STR_W, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
+ IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzPathRight, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
+
+ return S_OK;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // Checks if the path provided is valid within the specified constraints.
+ // ***NOTE: does not yet check for invalid path characters.
+ static bool
+ IsValid(LPCWSTR wzPath, DWORD cchPath, bool fAllowLongFormat)
+ {
+ if (clr::str::IsNullOrEmpty(wzPath))
+ return false;
+
+ bool fIsLongFormat = HasLongFormatPrefix(wzPath);
+
+ if (fIsLongFormat && !fAllowLongFormat)
+ return false;
+
+ if (!fIsLongFormat && cchPath > _MAX_PATH)
+ return false;
+
+ return true;
+ }
+ };
+ }
+}
+
+#endif // _clr_fs_Path_h_
diff --git a/src/inc/clr/stack.h b/src/inc/clr/stack.h
new file mode 100644
index 0000000000..f9741b274f
--- /dev/null
+++ b/src/inc/clr/stack.h
@@ -0,0 +1,99 @@
+// 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.
+//
+
+//
+// This header provides a basic stack implementation
+
+#ifndef _clr_Stack_h_
+#define _clr_Stack_h_
+
+namespace clr
+{
+ //-------------------------------------------------------------------------------------------------
+ // A basic stack class.
+ //
+ template < typename T >
+ class Stack
+ {
+ private:
+ //---------------------------------------------------------------------------------------------
+ struct Link
+ {
+ template < typename A1 >
+ Link(A1 && a1, Link * next = nullptr)
+ : _value(std::forward<A1>(a1))
+ , _next(next)
+ {}
+
+ T _value;
+ Link * _next;
+ };
+
+ public:
+ //---------------------------------------------------------------------------------------------
+ // Empty stack constructor.
+ Stack()
+ : _top(nullptr)
+ , _size(0)
+ {}
+
+ //---------------------------------------------------------------------------------------------
+ // Move constructor.
+ Stack(Stack && stack)
+ : _top(nullptr)
+ , _size(0)
+ { *this = std::move(stack); }
+
+ //---------------------------------------------------------------------------------------------
+ ~Stack()
+ {
+ while (!empty())
+ {
+ pop();
+ }
+ }
+
+ //---------------------------------------------------------------------------------------------
+ // Move assignment.
+ Stack& operator=(Stack && stack)
+ { std::swap(_top, stack._top); std::swap(_size, stack._size); }
+
+ //---------------------------------------------------------------------------------------------
+ bool empty() const
+ { return _top == nullptr; }
+
+ //---------------------------------------------------------------------------------------------
+ size_t size() const
+ { return _size; }
+
+ //---------------------------------------------------------------------------------------------
+ T & top()
+ { return _top->_value; }
+
+ //---------------------------------------------------------------------------------------------
+ T const & top() const
+ { return _top->_value; }
+
+ //---------------------------------------------------------------------------------------------
+ template < typename A1 > inline
+ void push(A1 && value)
+ {
+ STATIC_CONTRACT_THROWS;
+ _top = new Link(std::forward<A1>(value), _top);
+ ++_size;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ void pop()
+ { Link * del = _top; _top = _top->_next; --_size; delete del; }
+
+ private:
+ //---------------------------------------------------------------------------------------------
+ Link * _top;
+ size_t _size;
+ };
+} // namespace clr
+
+#endif // _clr_Stack_h_
diff --git a/src/inc/clr/str.h b/src/inc/clr/str.h
new file mode 100644
index 0000000000..94c8ed46b5
--- /dev/null
+++ b/src/inc/clr/str.h
@@ -0,0 +1,28 @@
+// 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.
+//
+
+//
+// This header provides general standard string services.
+//
+
+#ifndef _clr_str_h_
+#define _clr_str_h_
+
+namespace clr
+{
+ namespace str
+ {
+ //-----------------------------------------------------------------------------------------
+ // Returns true if the provided string is a null pointer or the empty string.
+ static inline bool
+ IsNullOrEmpty(LPCWSTR wzStr)
+ {
+ return wzStr == nullptr || *wzStr == W('\0');
+ }
+ }
+}
+
+#endif // _clr_str_h_
+
diff --git a/src/inc/clr/win32.h b/src/inc/clr/win32.h
new file mode 100644
index 0000000000..a0e00c6321
--- /dev/null
+++ b/src/inc/clr/win32.h
@@ -0,0 +1,38 @@
+// 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.
+//
+// clr/win32.h
+//
+// Provides Win32-specific utility functionality.
+//
+
+//
+
+#ifndef clr_win32_h
+#define clr_win32_h
+
+#include "winwrap.h"
+
+namespace clr
+{
+ namespace win32
+ {
+ // Prevents an HMODULE from being unloaded until process termination.
+ inline
+ HRESULT PreventModuleUnload(HMODULE hMod)
+ {
+ if (!WszGetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
+ reinterpret_cast<LPCTSTR>(hMod),
+ &hMod))
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+
+ return S_OK;
+ }
+ } // namespace win
+} // namespace clr
+
+#endif // clr_win32_h