238 lines
9.2 KiB
C++
238 lines
9.2 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
virtualizationInstance.h
|
|
|
|
Abstract:
|
|
|
|
The VirtualizationInstance class is a thin C++ wrapper around the ProjFS C API. The ProjFS API
|
|
is available starting with Windows 10 October 2018 Update (Windows 10 version 1809) and Windows
|
|
Server 2019.
|
|
|
|
A ProjFS provider written in C++ can derive from this class. The provider satisfies requests from
|
|
ProjFS by overriding the virtual methods in this class.
|
|
|
|
The provider must override the following pure virtual methods, which represent mandatory ProjFS
|
|
callbacks:
|
|
|
|
1.a) StartDirEnum
|
|
1.b) GetDirEnum
|
|
1.c) EndDirEnum
|
|
To answer the question 'what are the files and folders under a given folder'
|
|
2) GetPlaceholderInfo
|
|
To answer the question 'what is the meta data for a given file (file attributes, timestamps etc)'
|
|
3) GetFileData
|
|
To answer the question 'what is the data for a given file'
|
|
|
|
The provider may choose to override the following methods to implement extended functionality:
|
|
|
|
5) Notify
|
|
If the provider wants to receive notifications of file system operations.
|
|
See PRJ_NOTIFICATION_TYPE enum in projectedfslib.h for a full list of notification types.
|
|
|
|
6) QueryFileName
|
|
Called to determine whether a particular file exists in the provider's backing store. If the
|
|
provider does not implement this callback, ProjFS will call the enumeration callbacks to find
|
|
the file.
|
|
|
|
7) CancelCommand
|
|
If the provider wants to handle cancellation of I/O, such as if a user presses CRTL-C or kills
|
|
the process while a callback is being processed.
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
namespace regfs {
|
|
|
|
struct GUIDComparer {
|
|
bool operator()(const GUID & Left, const GUID & Right) const
|
|
{
|
|
return memcmp(&Left, &Right, sizeof(Right)) < 0;
|
|
}
|
|
};
|
|
|
|
enum OptionalMethods {
|
|
None = 0,
|
|
Notify = 0x1,
|
|
QueryFileName = 0x2,
|
|
CancelCommand = 0x4
|
|
};
|
|
DEFINE_ENUM_FLAG_OPERATORS(OptionalMethods);
|
|
|
|
class NotImplemented : public std::logic_error {
|
|
public:
|
|
NotImplemented() : std::logic_error("Function not yet implemented")
|
|
{};
|
|
};
|
|
|
|
class VirtualizationInstance {
|
|
|
|
public:
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Virtualization instance control API wrappers (user mode -> kernel mode). The derived provider
|
|
// class should not override these methods.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Starts a virtualization instance at rootPath
|
|
HRESULT Start(LPCWSTR rootPath, PRJ_STARTVIRTUALIZING_OPTIONS* options = nullptr);
|
|
|
|
// Stops a virtualization instance
|
|
void Stop();
|
|
|
|
// Send file meta data information to ProjFS, ProjFS will create an on-disk placeholder for the path.
|
|
HRESULT WritePlaceholderInfo(LPCWSTR relativePath,
|
|
PRJ_PLACEHOLDER_INFO* placeholderInfo,
|
|
DWORD length);
|
|
|
|
// Send file contents to ProjFS, ProjFS will write the data into the target placeholder file
|
|
// and convert it to hydrated placeholder state.
|
|
HRESULT WriteFileData(LPCGUID streamId,
|
|
PVOID buffer,
|
|
ULONGLONG byteOffset,
|
|
DWORD length);
|
|
|
|
protected:
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Virtualization instance callbacks (kernel mode -> user mode). These are the methods the derived
|
|
// provider class overrides.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// [Mandatory] Inform the provider a directory enumeration is starting.
|
|
// It corresponds to PRJ_START_DIRECTORY_ENUMERATION_CB in projectedfslib.h
|
|
virtual HRESULT StartDirEnum(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ const GUID* EnumerationId
|
|
) = 0;
|
|
|
|
// [Mandatory] Inform the provider a directory enumeration is over.
|
|
// It corresponds to PRJ_END_DIRECTORY_ENUMERATION_CB in projectedfslib.h
|
|
virtual HRESULT EndDirEnum(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ const GUID* EnumerationId
|
|
) = 0;
|
|
|
|
// [Mandatory] Request directory enumeration information from the provider.
|
|
// It corresponds to PRJ_GET_DIRECTORY_ENUMERATION_CB in projectedfslib.h
|
|
virtual HRESULT GetDirEnum(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ const GUID* EnumerationId,
|
|
_In_opt_ PCWSTR SearchExpression,
|
|
_In_ PRJ_DIR_ENTRY_BUFFER_HANDLE DirEntryBufferHandle
|
|
) = 0;
|
|
|
|
// [Mandatory] Request meta data information for a file or directory.
|
|
// It corresponds to PRJ_GET_PLACEHOLDER_INFO_CB in projectedfslib.h
|
|
virtual HRESULT GetPlaceholderInfo(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
) = 0;
|
|
|
|
// [Mandatory] Request the contents of a file's primary data stream.
|
|
// It corresponds to PRJ_GET_FILE_DATA_CB in projectedfslib.h
|
|
virtual HRESULT GetFileData(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ UINT64 ByteOffset,
|
|
_In_ UINT32 Length
|
|
) = 0;
|
|
|
|
// [Optional] Deliver notifications to the provider that it has specified
|
|
// it wishes to receive. It corresponds to PRJ_NOTIFICATION_CB in projectedfslib.h
|
|
virtual HRESULT Notify(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ BOOLEAN IsDirectory,
|
|
_In_ PRJ_NOTIFICATION NotificationType,
|
|
_In_opt_ PCWSTR DestinationFileName,
|
|
_Inout_ PRJ_NOTIFICATION_PARAMETERS* NotificationParameters
|
|
);
|
|
|
|
virtual HRESULT QueryFileName(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
);
|
|
|
|
virtual void CancelCommand(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Getter/Setter methods. The derived provider class (RegfsProvider) uses SetOptionalMethods()
|
|
// to indicate which optional callbacks it overrode. This is required because ProjFS detects
|
|
// whether a provider implemented an optional callback by whether or not the provider supplied
|
|
// a pointer to the callback in the callbacks parameter of PrjStartVirtualizing().
|
|
// VirtualizationInstance::Start() uses GetOptionalMethods() to find out which optional callbacks
|
|
// were implemented, and sets the corresponding C callback into the callbacks parameter.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
virtual OptionalMethods GetOptionalMethods() final;
|
|
virtual void SetOptionalMethods(OptionalMethods optionalMethodsToSet) final;
|
|
|
|
private:
|
|
|
|
PRJ_STARTVIRTUALIZING_OPTIONS _options = {};
|
|
PRJ_CALLBACKS _callbacks = {};
|
|
OptionalMethods _implementedOptionalMethods = OptionalMethods::None;
|
|
const std::wstring _instanceIdFile = LR"(\.regfsId)";
|
|
|
|
HRESULT EnsureVirtualizationRoot();
|
|
|
|
protected:
|
|
|
|
std::wstring _rootPath;
|
|
PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT _instanceHandle = nullptr;
|
|
|
|
private:
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Prototypes of the ProjFS C callbacks. ProjFS will call these, and they in turn will call
|
|
// the VirtualizationInstance class methods.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT StartDirEnumCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ const GUID* EnumerationId
|
|
);
|
|
|
|
static HRESULT EndDirEnumCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* callbackData,
|
|
_In_ const GUID* EnumerationId
|
|
);
|
|
|
|
static HRESULT GetDirEnumCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ const GUID* EnumerationId,
|
|
_In_opt_ PCWSTR SearchExpression,
|
|
_In_ PRJ_DIR_ENTRY_BUFFER_HANDLE DirEntryBufferHandle
|
|
);
|
|
|
|
static HRESULT GetPlaceholderInfoCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
);
|
|
|
|
static HRESULT GetFileDataCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ UINT64 ByteOffset,
|
|
_In_ UINT32 Length
|
|
);
|
|
|
|
static HRESULT NotificationCallback_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData,
|
|
_In_ BOOLEAN IsDirectory,
|
|
_In_ PRJ_NOTIFICATION NotificationType,
|
|
_In_opt_ PCWSTR DestinationFileName,
|
|
_Inout_ PRJ_NOTIFICATION_PARAMETERS* NotificationParameters
|
|
);
|
|
|
|
static HRESULT QueryFileName_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
);
|
|
|
|
static void CancelCommand_C(
|
|
_In_ const PRJ_CALLBACK_DATA* CallbackData
|
|
);
|
|
};
|
|
|
|
} |