1 | // Licensed to the .NET Foundation under one or more agreements. |
---|---|
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | |
6 | // |
7 | // This header provides general directory-related file system services. |
8 | |
9 | #ifndef _clr_fs_Dir_h_ |
10 | #define _clr_fs_Dir_h_ |
11 | |
12 | #include "clrtypes.h" |
13 | #include "clr/str.h" |
14 | #include "strsafe.h" |
15 | |
16 | #ifndef countof |
17 | #define countof(x) (sizeof(x) / sizeof(x[0])) |
18 | #endif // !countof |
19 | |
20 | namespace clr |
21 | { |
22 | namespace fs |
23 | { |
24 | class Dir |
25 | { |
26 | public: |
27 | static inline bool Exists( |
28 | LPCWSTR wzDirPath) |
29 | { |
30 | DWORD attrs = WszGetFileAttributes(wzDirPath); |
31 | return (attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_DIRECTORY); |
32 | } |
33 | |
34 | //----------------------------------------------------------------------------------------- |
35 | // Creates new directory indicated by wzDirPath. |
36 | // |
37 | // Returns: |
38 | // S_OK - on success directory creation |
39 | // S_FALSE - when directory previously existed |
40 | // HR(ERROR_PATH_NOT_FOUND) - when creation of dir fails. |
41 | static inline HRESULT Create( |
42 | LPCWSTR wzDirPath) |
43 | { |
44 | HRESULT hr = S_OK; |
45 | |
46 | if (!WszCreateDirectory(wzDirPath, nullptr)) |
47 | { |
48 | hr = HRESULT_FROM_GetLastError(); |
49 | if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) |
50 | { |
51 | hr = S_FALSE; |
52 | } |
53 | } |
54 | return hr; |
55 | } |
56 | |
57 | //----------------------------------------------------------------------------------------- |
58 | // Creates the specified directory and all required subdirectories. wzDirPath will be |
59 | // temporarily modified in the process. |
60 | // |
61 | // Returns: |
62 | // S_OK - on success directory creation |
63 | // S_FALSE - when directory previously existed |
64 | // HR(ERROR_PATH_NOT_FOUND) - when creation of any dir fails. |
65 | static inline HRESULT CreateRecursively( |
66 | __inout_z LPWSTR wzDirPath, |
67 | size_t cchDirPath = 0) |
68 | { |
69 | HRESULT hr = S_OK; |
70 | |
71 | if (wzDirPath == nullptr) |
72 | { |
73 | return E_POINTER; |
74 | } |
75 | |
76 | if (cchDirPath == 0) |
77 | { |
78 | cchDirPath = wcslen(wzDirPath); |
79 | } |
80 | |
81 | // Try to create the path. If it fails, assume that's because the parent folder does |
82 | // not exist. Try to create the parent then re-attempt. |
83 | WCHAR chOrig = wzDirPath[cchDirPath]; |
84 | hr = Create(wzDirPath); |
85 | if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) |
86 | { |
87 | for (WCHAR* pCurCh = wzDirPath + cchDirPath - 1; pCurCh != wzDirPath; --pCurCh) |
88 | { |
89 | if (*pCurCh == W('\\') || *pCurCh == W('\0')) |
90 | { |
91 | WCHAR chOrig = *pCurCh; |
92 | *pCurCh = W('\0'); |
93 | IfFailRet(CreateRecursively(wzDirPath, pCurCh - wzDirPath)); |
94 | *pCurCh = chOrig; |
95 | break; |
96 | } |
97 | } |
98 | IfFailRet(Create(wzDirPath)); |
99 | } |
100 | |
101 | return hr; |
102 | } |
103 | |
104 | //----------------------------------------------------------------------------------------- |
105 | // Creates the specified directory and all required subdirectories. |
106 | static inline HRESULT CreateRecursively( |
107 | LPCWSTR wzDirPath) |
108 | { |
109 | HRESULT hr = S_OK; |
110 | |
111 | if (wzDirPath == nullptr) |
112 | { |
113 | return E_POINTER; |
114 | } |
115 | |
116 | // Make a writable copy of wzDirPath |
117 | size_t cchDirPath = wcslen(wzDirPath); |
118 | CQuickWSTR wzBuffer; |
119 | IfFailRet(wzBuffer.ReSizeNoThrow(cchDirPath + 1)); |
120 | wcscpy_s(wzBuffer.Ptr(), wzBuffer.Size(), wzDirPath); |
121 | IfFailRet(CreateRecursively(wzBuffer.Ptr(), cchDirPath)); |
122 | |
123 | return hr; |
124 | } |
125 | }; |
126 | } |
127 | } |
128 | |
129 | #endif // _clr_fs_Dir_h_ |
130 |