2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
8 // This header provides general path-related file system services.
10 #ifndef _clr_fs_Path_h_
11 #define _clr_fs_Path_h_
14 #include "cor.h" // SELECTANY
20 #ifndef LONG_FORMAT_PATH_PREFIX
21 #define LONG_FORMAT_PATH_PREFIX W("\\\\?\\")
28 // This list taken from ndp/clr/src/bcl/system/io/path.cs
29 SELECTANY WCHAR const g_rgInvalidPathChars[] =
30 { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6,
31 (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14,
32 (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22,
33 (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30,
39 //-----------------------------------------------------------------------------------------
44 DWORD attrs = WszGetFileAttributes(wzPath);
45 return (attrs != INVALID_FILE_ATTRIBUTES);
48 //-----------------------------------------------------------------------------------------
49 // Returns true if wzPath represents a long format path (i.e., prefixed with '\\?\').
51 HasLongFormatPrefix(LPCWSTR wzPath)
53 _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
54 return wcscmp(wzPath, LONG_FORMAT_PATH_PREFIX) == 0;
57 //-----------------------------------------------------------------------------------------
59 HasUncPrefix(LPCWSTR wzPath)
61 _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
62 return wzPath[0] != W('\0') && wzPath[0] == W('\\')
63 && wzPath[1] != W('\0') && wzPath[1] == W('\\')
64 && wzPath[2] != W('\0') && wzPath[2] != W('?');
67 //-----------------------------------------------------------------------------------------
69 HasDrivePrefix(LPCWSTR wzPath)
71 _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
72 return wzPath[0] != W('\0')
73 && wzPath[1] != W('\0') && wzPath[1] == W(':')
74 && ((wzPath[0] >= W('a') && wzPath[0] <= W('z')) ||
75 (wzPath[0] >= W('A') && wzPath[0] <= W('Z')));
78 //-----------------------------------------------------------------------------------------
79 // Returns true if wzPath represents a relative path.
81 IsRelative(LPCWSTR wzPath)
83 _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
84 return !HasLongFormatPrefix(wzPath)
85 && !HasUncPrefix(wzPath)
86 && (!HasDrivePrefix(wzPath) || wzPath[2] != W('\\'));
89 //-----------------------------------------------------------------------------------------
90 // Combines two path parts. wzPathLeft must be a directory path and may be either absolute
91 // or relative. wzPathRight may be a directory or file path and must be relative. The
92 // result is placed in wzBuffer and the number of chars written is placed in pcchBuffer on
93 // success; otherwise an error HRESULT is returned.
95 Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __out DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer)
97 STATIC_CONTRACT_NOTHROW;
101 if (clr::str::IsNullOrEmpty(wzPathLeft) || clr::str::IsNullOrEmpty(wzPathRight) || pcchBuffer == nullptr)
104 LPWSTR wzBuf = wzBuffer;
105 size_t cchBuf = *pcchBuffer;
107 IfFailRet(StringCchCopyExW(wzBuf, cchBuf, wzPathLeft, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
108 IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == W('\\') ? W("") : W("\\"), &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
109 IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzPathRight, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
114 //-----------------------------------------------------------------------------------------
115 // Checks if the path provided is valid within the specified constraints.
116 // ***NOTE: does not yet check for invalid path characters.
118 IsValid(LPCWSTR wzPath, DWORD cchPath, bool fAllowLongFormat)
120 if (clr::str::IsNullOrEmpty(wzPath))
123 bool fIsLongFormat = HasLongFormatPrefix(wzPath);
125 if (fIsLongFormat && !fAllowLongFormat)
128 if (!fIsLongFormat && cchPath > _MAX_PATH)
137 #endif // _clr_fs_Path_h_