Skip to content

Commit 3417d3a

Browse files
author
yerudako
committed
(cgallred) Consolidate-API-version-handling
1 parent 34e010f commit 3417d3a

5 files changed

Lines changed: 115 additions & 77 deletions

File tree

ProjectedFSLib.Managed.API/ApiHelper.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ using namespace System::IO;
1111
using namespace Microsoft::Windows::ProjFS;
1212

1313
ApiHelper::ApiHelper() :
14-
useRS5Api(false)
14+
supportedApi(ApiLevel::v1803)
1515
{
1616
auto projFsLib = ::LoadLibraryW(L"ProjectedFSLib.dll");
1717
if (!projFsLib)
@@ -22,6 +22,7 @@ ApiHelper::ApiHelper() :
2222
if (::GetProcAddress(projFsLib, "PrjStartVirtualizing") != nullptr)
2323
{
2424
// We have the API introduced in Windows 10 version 1809.
25+
this->supportedApi = ApiLevel::v1809;
2526

2627
this->_PrjStartVirtualizing = reinterpret_cast<t_PrjStartVirtualizing>(::GetProcAddress(projFsLib,
2728
"PrjStartVirtualizing"));
@@ -52,9 +53,12 @@ ApiHelper::ApiHelper() :
5253
if (::GetProcAddress(projFsLib, "PrjWritePlaceholderInfo2") != nullptr)
5354
{
5455
// We have the API introduced in Windows 10 version 2004.
56+
this->supportedApi = ApiLevel::v2004;
57+
5558
this->_PrjWritePlaceholderInfo2 = reinterpret_cast<t_PrjWritePlaceholderInfo2>(::GetProcAddress(projFsLib,
5659
"PrjWritePlaceholderInfo2"));
57-
this->useSymlinkApi = true;
60+
61+
this->_PrjFillDirEntryBuffer2 = reinterpret_cast<t_PrjFillDirEntryBuffer2>(::GetProcAddress(projFsLib, "PrjFillDirEntryBuffer2"));
5862
}
5963

6064
::FreeLibrary(projFsLib);
@@ -63,7 +67,6 @@ ApiHelper::ApiHelper() :
6367
!this->_PrjStopVirtualizing ||
6468
!this->_PrjWriteFileData ||
6569
!this->_PrjWritePlaceholderInfo ||
66-
(this->useSymlinkApi && !this->_PrjWritePlaceholderInfo2) ||
6770
!this->_PrjAllocateAlignedBuffer ||
6871
!this->_PrjFreeAlignedBuffer ||
6972
!this->_PrjGetVirtualizationInstanceInfo ||
@@ -74,7 +77,15 @@ ApiHelper::ApiHelper() :
7477
"Could not get a required entry point."));
7578
}
7679

77-
this->useRS5Api = true;
80+
if (this->supportedApi >= ApiLevel::v2004)
81+
{
82+
if (!this->_PrjWritePlaceholderInfo2 ||
83+
!this->_PrjFillDirEntryBuffer2)
84+
{
85+
throw gcnew EntryPointNotFoundException(String::Format(CultureInfo::InvariantCulture,
86+
"Could not get a required entry point."));
87+
}
88+
}
7889
}
7990
else if (::GetProcAddress(projFsLib, "PrjStartVirtualizationInstance") == nullptr)
8091
{
@@ -135,7 +146,12 @@ ApiHelper::ApiHelper() :
135146
}
136147
}
137148

138-
bool ApiHelper::UseRS5Api::get(void)
149+
bool ApiHelper::UseBetaApi::get(void)
139150
{
140-
return this->useRS5Api;
141-
}
151+
return (this->supportedApi == ApiLevel::v1803);
152+
}
153+
154+
ApiLevel ApiHelper::SupportedApi::get(void)
155+
{
156+
return this->supportedApi;
157+
}

ProjectedFSLib.Managed.API/ApiHelper.h

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@
66
namespace Microsoft {
77
namespace Windows {
88
namespace ProjFS {
9+
/// <summary>
10+
/// Defines values describing the APIs available from this wrapper.
11+
/// </summary>
12+
enum class ApiLevel : short
13+
{
14+
/// <summary>Using Windows 10 version 1803 beta API.</summary>
15+
v1803 = 1803,
16+
17+
/// <summary>Using Windows 10 version 1809 API.</summary>
18+
v1809 = 1809,
19+
20+
/// <summary>Adding APIs introduced in Windows 10 version 2004.</summary>
21+
v2004 = 2004,
22+
};
923
/// <summary>Helper class for using the correct native APIs in the managed layer.</summary>
1024
/// <remarks>
1125
/// <para>
@@ -32,13 +46,37 @@ ref class ApiHelper {
3246
internal:
3347
ApiHelper();
3448

35-
property bool UseRS5Api
49+
property bool UseBetaApi
3650
{
3751
bool get(void);
38-
};
52+
}
53+
54+
property ApiLevel SupportedApi
55+
{
56+
ApiLevel get(void);
57+
}
3958

4059
private:
4160

61+
#pragma region Signatures for Windows 10 version 2004 APIs
62+
63+
typedef HRESULT(__stdcall* t_PrjWritePlaceholderInfo2)(
64+
_In_ PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext,
65+
_In_ PCWSTR destinationFileName,
66+
_In_reads_bytes_(placeholderInfoSize) const PRJ_PLACEHOLDER_INFO* placeholderInfo,
67+
_In_ UINT32 placeholderInfoSize,
68+
_In_opt_ const PRJ_EXTENDED_INFO* ExtendedInfo
69+
);
70+
71+
typedef HRESULT(__stdcall* t_PrjFillDirEntryBuffer2) (
72+
_In_ PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle,
73+
_In_ PCWSTR fileName,
74+
_In_opt_ PRJ_FILE_BASIC_INFO* fileBasicInfo,
75+
_In_opt_ PRJ_EXTENDED_INFO* extendedInfo
76+
);
77+
78+
#pragma endregion
79+
4280
#pragma region Signatures for Windows 10 version 1809 APIs
4381

4482
typedef HRESULT (__stdcall* t_PrjStartVirtualizing)(
@@ -68,14 +106,6 @@ ref class ApiHelper {
68106
_In_ UINT32 placeholderInfoSize
69107
);
70108

71-
typedef HRESULT(__stdcall* t_PrjWritePlaceholderInfo2)(
72-
_In_ PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext,
73-
_In_ PCWSTR destinationFileName,
74-
_In_reads_bytes_(placeholderInfoSize) const PRJ_PLACEHOLDER_INFO* placeholderInfo,
75-
_In_ UINT32 placeholderInfoSize,
76-
_In_opt_ const PRJ_EXTENDED_INFO* ExtendedInfo
77-
);
78-
79109
typedef void* (__stdcall* t_PrjAllocateAlignedBuffer)(
80110
_In_ PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext,
81111
_In_ size_t size
@@ -177,13 +207,13 @@ ref class ApiHelper {
177207

178208
#pragma endregion
179209

180-
bool useRS5Api;
181-
bool useSymlinkApi;
210+
ApiLevel supportedApi{ ApiLevel::v1803 };
182211

183212
internal:
184213

185214
// 2004 API
186215
t_PrjWritePlaceholderInfo2 _PrjWritePlaceholderInfo2 = nullptr;
216+
t_PrjFillDirEntryBuffer2 _PrjFillDirEntryBuffer2 = nullptr;
187217

188218
// 1809 API
189219
t_PrjStartVirtualizing _PrjStartVirtualizing = nullptr;

ProjectedFSLib.Managed.API/DirectoryEnumerationResults.h

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include "IDirectoryEnumerationResults.h"
7+
#include "ApiHelper.h"
78

89
using namespace System;
910
using namespace System::Globalization;
@@ -22,25 +23,9 @@ namespace ProjFS {
2223
public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResults {
2324
internal:
2425

25-
DirectoryEnumerationResults(PRJ_DIR_ENTRY_BUFFER_HANDLE bufferHandle)
26-
{
27-
m_dirEntryBufferHandle = bufferHandle;
28-
29-
auto projFsLib = ::LoadLibraryW(L"ProjectedFSLib.dll");
30-
if (!projFsLib)
31-
{
32-
throw gcnew FileLoadException(String::Format(CultureInfo::InvariantCulture, "Could not load ProjectedFSLib.dll to set up entry points."));
33-
}
34-
35-
if (::GetProcAddress(projFsLib, "PrjWritePlaceholderInfo2") != nullptr)
36-
{
37-
// We have the API introduced in Windows 10 version 2004.
38-
this->_PrjFillDirEntryBuffer2 = reinterpret_cast<t_PrjFillDirEntryBuffer2>(::GetProcAddress(projFsLib,
39-
"PrjFillDirEntryBuffer2"));
40-
}
41-
42-
::FreeLibrary(projFsLib);
43-
}
26+
DirectoryEnumerationResults(PRJ_DIR_ENTRY_BUFFER_HANDLE bufferHandle, ApiHelper^ apiHelper) :
27+
m_dirEntryBufferHandle(bufferHandle), m_apiHelper(apiHelper)
28+
{ }
4429

4530
// Provides access to the native handle to the directory entry buffer.
4631
// Used internally by VirtualizationInstance::CompleteCommand(int, IDirectoryEnumerationResults^).
@@ -227,6 +212,13 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
227212
System::DateTime changeTime,
228213
System::String^ symlinkTargetOrNull) sealed
229214
{
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+
230222
ValidateFileName(fileName);
231223

232224
pin_ptr<const WCHAR> pFileName = PtrToStringChars(fileName);
@@ -238,27 +230,20 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
238230
lastWriteTime,
239231
changeTime);
240232

241-
HRESULT hr;
242-
if (symlinkTargetOrNull != nullptr && this->_PrjFillDirEntryBuffer2 != nullptr)
233+
PRJ_EXTENDED_INFO extendedInfo = {};
234+
if (symlinkTargetOrNull != nullptr)
243235
{
244-
PRJ_EXTENDED_INFO extendedInfo = {};
245-
246236
extendedInfo.InfoType = PRJ_EXT_INFO_TYPE_SYMLINK;
247237
pin_ptr<const WCHAR> targetPath = PtrToStringChars(symlinkTargetOrNull);
248238
extendedInfo.Symlink.TargetName = targetPath;
249-
250-
hr = this->_PrjFillDirEntryBuffer2(m_dirEntryBufferHandle,
251-
pFileName,
252-
&basicInfo,
253-
&extendedInfo);
254-
}
255-
else
256-
{
257-
hr = ::PrjFillDirEntryBuffer(pFileName,
258-
&basicInfo,
259-
m_dirEntryBufferHandle);
260239
}
261240

241+
HRESULT hr;
242+
hr = m_apiHelper->_PrjFillDirEntryBuffer2(m_dirEntryBufferHandle,
243+
pFileName,
244+
&basicInfo,
245+
(symlinkTargetOrNull != nullptr) ? &extendedInfo : nullptr);
246+
262247
if FAILED(hr)
263248
{
264249
return false;
@@ -270,6 +255,7 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
270255
private:
271256

272257
PRJ_DIR_ENTRY_BUFFER_HANDLE m_dirEntryBufferHandle;
258+
ApiHelper^ m_apiHelper;
273259

274260
void ValidateFileName(System::String^ fileName)
275261
{
@@ -316,14 +302,5 @@ public ref class DirectoryEnumerationResults : public IDirectoryEnumerationResul
316302

317303
return basicInfo;
318304
}
319-
320-
typedef HRESULT(__stdcall* t_PrjFillDirEntryBuffer2)(
321-
_In_ PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle,
322-
_In_ PCWSTR fileName,
323-
_In_opt_ PRJ_FILE_BASIC_INFO* fileBasicInfo,
324-
_In_opt_ PRJ_EXTENDED_INFO* extendedInfo
325-
);
326-
327-
t_PrjFillDirEntryBuffer2 _PrjFillDirEntryBuffer2 = nullptr;
328305
};
329306
}}} // namespace Microsoft.Windows.ProjFS

0 commit comments

Comments
 (0)