diff options
Diffstat (limited to 'src/inc/clr')
-rw-r--r-- | src/inc/clr/fs.h | 16 | ||||
-rw-r--r-- | src/inc/clr/fs/dir.h | 129 | ||||
-rw-r--r-- | src/inc/clr/fs/file.h | 40 | ||||
-rw-r--r-- | src/inc/clr/fs/path.h | 141 | ||||
-rw-r--r-- | src/inc/clr/stack.h | 99 | ||||
-rw-r--r-- | src/inc/clr/str.h | 28 | ||||
-rw-r--r-- | src/inc/clr/win32.h | 38 |
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 |