4
4
#pragma once
5
5
6
6
#include " IDirectoryEnumerationResults.h"
7
+ #include " ApiHelper.h"
8
+
9
+ using namespace System ;
10
+ using namespace System ::Globalization;
11
+ using namespace System ::IO;
7
12
8
13
namespace Microsoft {
9
14
namespace Windows {
@@ -18,10 +23,9 @@ namespace ProjFS {
18
23
public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResults {
19
24
internal:
20
25
21
- DirectoryEnumerationResults (PRJ_DIR_ENTRY_BUFFER_HANDLE bufferHandle)
22
- {
23
- m_dirEntryBufferHandle = bufferHandle;
24
- }
26
+ DirectoryEnumerationResults (PRJ_DIR_ENTRY_BUFFER_HANDLE bufferHandle, ApiHelper^ apiHelper) :
27
+ m_dirEntryBufferHandle (bufferHandle), m_apiHelper(apiHelper)
28
+ { }
25
29
26
30
// Provides access to the native handle to the directory entry buffer.
27
31
// Used internally by VirtualizationInstance::CompleteCommand(int, IDirectoryEnumerationResults^).
@@ -139,14 +143,137 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
139
143
System::DateTime lastAccessTime,
140
144
System::DateTime lastWriteTime,
141
145
System::DateTime changeTime) sealed
146
+ {
147
+ ValidateFileName (fileName);
148
+
149
+ pin_ptr<const WCHAR> pFileName = PtrToStringChars (fileName);
150
+ PRJ_FILE_BASIC_INFO basicInfo = BuildFileBasicInfo (fileSize,
151
+ isDirectory,
152
+ fileAttributes,
153
+ creationTime,
154
+ lastAccessTime,
155
+ lastWriteTime,
156
+ changeTime);
157
+
158
+ auto hr = ::PrjFillDirEntryBuffer (pFileName,
159
+ &basicInfo,
160
+ m_dirEntryBufferHandle);
161
+
162
+ if FAILED (hr)
163
+ {
164
+ return false ;
165
+ }
166
+
167
+ return true ;
168
+ }
169
+
170
+ // / <summary>Adds one entry to a directory enumeration result.</summary>
171
+ // / <remarks>
172
+ // / <para>
173
+ // / In its implementation of a <c>GetDirectoryEnumerationCallback</c> delegate the provider
174
+ // / calls this method for each matching file or directory in the enumeration.
175
+ // / </para>
176
+ // / <para>
177
+ // / If this method returns <c>false</c>, the provider returns <see cref="HResult::Ok"/> and waits for
178
+ // / the next <c>GetDirectoryEnumerationCallback</c>. Then it resumes filling the enumeration with
179
+ // / the entry it was trying to add when it got <c>false</c>.
180
+ // / </para>
181
+ // / <para>
182
+ // / If the method returns <c>false</c> for the first file or directory in the enumeration, the
183
+ // / provider returns <see cref="HResult::InsufficientBuffer"/> from the <c>GetDirectoryEnumerationCallback</c>
184
+ // / method.
185
+ // / </para>
186
+ // / </remarks>
187
+ // / <param name="fileName">The name of the file or directory.</param>
188
+ // / <param name="fileSize">The size of the file.</param>
189
+ // / <param name="isDirectory"><c>true</c> if this item is a directory, <c>false</c> if it is a file.</param>
190
+ // / <param name="fileAttributes">The file attributes.</param>
191
+ // / <param name="creationTime">The time the file was created.</param>
192
+ // / <param name="lastAccessTime">The time the file was last accessed.</param>
193
+ // / <param name="lastWriteTime">The time the file was last written to.</param>
194
+ // / <param name="changeTime">The time the file was last changed.</param>
195
+ // / <param name="symlinkTargetOrNull">Specifies the symlink target path if the file is a symlink.</param>
196
+ // / <returns>
197
+ // / <para>
198
+ // / <c>true</c> if the entry was successfully added to the enumeration buffer, <c>false</c> otherwise.
199
+ // / </para>
200
+ // / </returns>
201
+ // / <exception cref="System::ArgumentException">
202
+ // / <paramref name="fileName"/> is null or empty.
203
+ // / </exception>
204
+ virtual bool Add (
205
+ System::String^ fileName,
206
+ long long fileSize,
207
+ bool isDirectory,
208
+ System::IO::FileAttributes fileAttributes,
209
+ System::DateTime creationTime,
210
+ System::DateTime lastAccessTime,
211
+ System::DateTime lastWriteTime,
212
+ System::DateTime changeTime,
213
+ System::String^ symlinkTargetOrNull) sealed
214
+ {
215
+ // This API is supported in Windows 10 version 2004 and above.
216
+ if ((symlinkTargetOrNull != nullptr ) &&
217
+ (m_apiHelper->SupportedApi < ApiLevel::v2004))
218
+ {
219
+ throw gcnew NotImplementedException (" PrjFillDirEntryBuffer2 is not supported in this version of Windows." );
220
+ }
221
+
222
+ ValidateFileName (fileName);
223
+
224
+ pin_ptr<const WCHAR> pFileName = PtrToStringChars (fileName);
225
+ PRJ_FILE_BASIC_INFO basicInfo = BuildFileBasicInfo (fileSize,
226
+ isDirectory,
227
+ fileAttributes,
228
+ creationTime,
229
+ lastAccessTime,
230
+ lastWriteTime,
231
+ changeTime);
232
+
233
+ PRJ_EXTENDED_INFO extendedInfo = {};
234
+ if (symlinkTargetOrNull != nullptr )
235
+ {
236
+ extendedInfo.InfoType = PRJ_EXT_INFO_TYPE_SYMLINK;
237
+ pin_ptr<const WCHAR> targetPath = PtrToStringChars (symlinkTargetOrNull);
238
+ extendedInfo.Symlink .TargetName = targetPath;
239
+ }
240
+
241
+ HRESULT hr;
242
+ hr = m_apiHelper->_PrjFillDirEntryBuffer2 (m_dirEntryBufferHandle,
243
+ pFileName,
244
+ &basicInfo,
245
+ (symlinkTargetOrNull != nullptr ) ? &extendedInfo : nullptr );
246
+
247
+ if FAILED (hr)
248
+ {
249
+ return false ;
250
+ }
251
+
252
+ return true ;
253
+ }
254
+
255
+ private:
256
+
257
+ PRJ_DIR_ENTRY_BUFFER_HANDLE m_dirEntryBufferHandle;
258
+ ApiHelper^ m_apiHelper;
259
+
260
+ void ValidateFileName (System::String^ fileName)
142
261
{
143
262
if (System::String::IsNullOrEmpty (fileName))
144
263
{
145
264
throw gcnew System::ArgumentException (System::String::Format (System::Globalization::CultureInfo::InvariantCulture,
146
- " fileName cannot be empty." ));
265
+ " fileName cannot be empty." ));
147
266
}
267
+ }
148
268
149
- pin_ptr<const WCHAR> pFileName = PtrToStringChars (fileName);
269
+ PRJ_FILE_BASIC_INFO BuildFileBasicInfo (long long fileSize,
270
+ bool isDirectory,
271
+ System::IO::FileAttributes fileAttributes,
272
+ System::DateTime creationTime,
273
+ System::DateTime lastAccessTime,
274
+ System::DateTime lastWriteTime,
275
+ System::DateTime changeTime)
276
+ {
150
277
PRJ_FILE_BASIC_INFO basicInfo = { 0 };
151
278
152
279
if (creationTime != System::DateTime::MinValue)
@@ -173,20 +300,7 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
173
300
basicInfo.IsDirectory = isDirectory;
174
301
basicInfo.FileSize = fileSize;
175
302
176
- auto hr = ::PrjFillDirEntryBuffer (pFileName,
177
- &basicInfo,
178
- m_dirEntryBufferHandle);
179
-
180
- if FAILED (hr)
181
- {
182
- return false ;
183
- }
184
-
185
- return true ;
303
+ return basicInfo;
186
304
}
187
-
188
- private:
189
-
190
- PRJ_DIR_ENTRY_BUFFER_HANDLE m_dirEntryBufferHandle;
191
305
};
192
306
}}} // namespace Microsoft.Windows.ProjFS
0 commit comments