aboutsummaryrefslogtreecommitdiff
path: root/zenserver
diff options
context:
space:
mode:
Diffstat (limited to 'zenserver')
-rw-r--r--zenserver/experimental/usnjournal.cpp351
-rw-r--r--zenserver/experimental/usnjournal.h69
-rw-r--r--zenserver/experimental/vfs.cpp3
-rw-r--r--zenserver/experimental/vfs.h5
-rw-r--r--zenserver/testing/launch.cpp565
-rw-r--r--zenserver/testing/launch.h48
-rw-r--r--zenserver/xmake.lua2
-rw-r--r--zenserver/zenserver.cpp31
-rw-r--r--zenserver/zenserver.rc24
9 files changed, 25 insertions, 1073 deletions
diff --git a/zenserver/experimental/usnjournal.cpp b/zenserver/experimental/usnjournal.cpp
deleted file mode 100644
index 580d71e45..000000000
--- a/zenserver/experimental/usnjournal.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#include <zencore/zencore.h>
-
-#if ZEN_PLATFORM_WINDOWS
-
-# include "usnjournal.h"
-
-# include <zencore/except.h>
-# include <zencore/logging.h>
-# include <zencore/timer.h>
-
-ZEN_THIRD_PARTY_INCLUDES_START
-# include <atlfile.h>
-ZEN_THIRD_PARTY_INCLUDES_END
-
-# include <filesystem>
-
-namespace zen {
-
-UsnJournalReader::UsnJournalReader()
-{
-}
-
-UsnJournalReader::~UsnJournalReader()
-{
- delete[] m_JournalReadBuffer;
-}
-
-bool
-UsnJournalReader::Initialize(std::filesystem::path VolumePath)
-{
- TCHAR VolumeName[MAX_PATH];
- TCHAR VolumePathName[MAX_PATH];
-
- {
- auto NativePath = VolumePath.native();
- BOOL Success = GetVolumePathName(NativePath.c_str(), VolumePathName, ZEN_ARRAY_COUNT(VolumePathName));
-
- if (!Success)
- {
- zen::ThrowLastError("GetVolumePathName failed");
- }
-
- Success = GetVolumeNameForVolumeMountPoint(VolumePathName, VolumeName, ZEN_ARRAY_COUNT(VolumeName));
-
- if (!Success)
- {
- zen::ThrowLastError("GetVolumeNameForVolumeMountPoint failed");
- }
-
- // Chop off trailing slash since we want to open a volume handle, not a handle to the volume root directory
-
- const size_t VolumeNameLength = wcslen(VolumeName);
-
- if (VolumeNameLength)
- {
- VolumeName[VolumeNameLength - 1] = '\0';
- }
- }
-
- m_VolumeHandle = CreateFile(VolumeName,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- nullptr, /* no custom security */
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- nullptr); /* template */
-
- if (m_VolumeHandle == INVALID_HANDLE_VALUE)
- {
- ThrowLastError("Volume handle open failed");
- }
-
- // Figure out which file system is in use for volume
-
- {
- WCHAR InfoVolumeName[MAX_PATH + 1]{};
- WCHAR FileSystemName[MAX_PATH + 1]{};
- DWORD MaximumComponentLength = 0;
- DWORD FileSystemFlags = 0;
-
- BOOL Success = GetVolumeInformationByHandleW(m_VolumeHandle,
- InfoVolumeName,
- MAX_PATH + 1,
- NULL,
- &MaximumComponentLength,
- &FileSystemFlags,
- FileSystemName,
- ZEN_ARRAY_COUNT(FileSystemName));
-
- if (!Success)
- {
- ThrowLastError("Failed to get volume information");
- }
-
- ZEN_DEBUG("File system type is {}", WideToUtf8(FileSystemName));
-
- if (wcscmp(L"ReFS", FileSystemName) == 0)
- {
- m_FileSystemType = FileSystemType::ReFS;
- }
- else if (wcscmp(L"NTFS", FileSystemName) == 0)
- {
- m_FileSystemType = FileSystemType::NTFS;
- }
- else
- {
- // Unknown file system type!
- }
- }
-
- // Determine if volume is on fast storage, where seeks aren't so expensive
-
- {
- STORAGE_PROPERTY_QUERY StorageQuery{};
- StorageQuery.PropertyId = StorageDeviceSeekPenaltyProperty;
- StorageQuery.QueryType = PropertyStandardQuery;
- DWORD BytesWritten;
- DEVICE_SEEK_PENALTY_DESCRIPTOR Result{};
-
- if (DeviceIoControl(m_VolumeHandle,
- IOCTL_STORAGE_QUERY_PROPERTY,
- &StorageQuery,
- sizeof(StorageQuery),
- &Result,
- sizeof(Result),
- &BytesWritten,
- nullptr))
- {
- m_IncursSeekPenalty = !!Result.IncursSeekPenalty;
- }
- }
-
- // Query Journal
-
- USN_JOURNAL_DATA_V2 UsnData{};
-
- {
- DWORD BytesWritten = 0;
-
- const BOOL Success =
- DeviceIoControl(m_VolumeHandle, FSCTL_QUERY_USN_JOURNAL, nullptr, 0, &UsnData, sizeof UsnData, &BytesWritten, nullptr);
-
- if (!Success)
- {
- switch (DWORD Error = GetLastError())
- {
- case ERROR_JOURNAL_NOT_ACTIVE:
- ZEN_INFO("No USN journal active on drive");
-
- // TODO: optionally activate USN journal on drive?
-
- ThrowSystemException(HRESULT_FROM_WIN32(Error), "No USN journal active on drive");
- break;
-
- default:
- ThrowSystemException(HRESULT_FROM_WIN32(Error), "FSCTL_QUERY_USN_JOURNAL failed");
- }
- }
- }
-
- m_JournalReadBuffer = new uint8_t[m_ReadBufferSize];
-
- // Catch up to USN start
-
- CAtlFile VolumeRootDir;
- HRESULT hRes =
- VolumeRootDir.Create(VolumePathName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS);
-
- if (FAILED(hRes))
- {
- ThrowSystemException(hRes, "Failed to open handle to volume root");
- }
-
- FILE_ID_INFO FileInformation{};
- BOOL Success = GetFileInformationByHandleEx(VolumeRootDir, FileIdInfo, &FileInformation, sizeof FileInformation);
-
- if (!Success)
- {
- ThrowLastError("GetFileInformationByHandleEx failed");
- }
-
- const Frn VolumeRootFrn = FileInformation.FileId;
-
- // Enumerate MFT (but not for ReFS)
-
- if (m_FileSystemType == FileSystemType::NTFS)
- {
- ZEN_INFO("Enumerating MFT for {}", WideToUtf8(VolumePathName));
-
- zen::Stopwatch Timer;
- uint64_t MftBytesProcessed = 0;
-
- MFT_ENUM_DATA_V1 MftEnumData{.StartFileReferenceNumber = 0, .LowUsn = 0, .HighUsn = 0, .MinMajorVersion = 2, .MaxMajorVersion = 3};
-
- BYTE MftBuffer[64 * 1024 + sizeof(DWORDLONG)];
- DWORD BytesWritten = 0;
-
- for (;;)
- {
- Success = DeviceIoControl(m_VolumeHandle,
- FSCTL_ENUM_USN_DATA,
- &MftEnumData,
- sizeof MftEnumData,
- MftBuffer,
- sizeof MftBuffer,
- &BytesWritten,
- nullptr);
-
- if (!Success)
- {
- DWORD Error = GetLastError();
-
- if (Error == ERROR_HANDLE_EOF)
- {
- break;
- }
-
- ThrowSystemException(HRESULT_FROM_WIN32(Error), "FSCTL_ENUM_USN_DATA failed");
- }
-
- void* BufferEnd = (void*)&MftBuffer[BytesWritten];
-
- // The enumeration call returns the next FRN ahead of the other data in the buffer
- MftEnumData.StartFileReferenceNumber = ((DWORDLONG*)MftBuffer)[0];
-
- PUSN_RECORD_UNION CommonRecord = PUSN_RECORD_UNION(&((DWORDLONG*)MftBuffer)[1]);
-
- while (CommonRecord < BufferEnd)
- {
- switch (CommonRecord->Header.MajorVersion)
- {
- case 2:
- {
- USN_RECORD_V2& Record = CommonRecord->V2;
-
- const Frn FileReference = Record.FileReferenceNumber;
- const Frn ParentReference = Record.ParentFileReferenceNumber;
- std::wstring_view FileName{Record.FileName, Record.FileNameLength};
- }
- break;
- case 3:
- {
- USN_RECORD_V3& Record = CommonRecord->V3;
-
- const Frn FileReference = Record.FileReferenceNumber;
- const Frn ParentReference = Record.ParentFileReferenceNumber;
- std::wstring_view FileName{Record.FileName, Record.FileNameLength};
- }
- break;
- case 4:
- {
- // This captures file modification ranges. We do not yet support this however
- USN_RECORD_V4& Record = CommonRecord->V4;
- ZEN_UNUSED(Record);
- }
- break;
- }
-
- const DWORD RecordLength = CommonRecord->Header.RecordLength;
- CommonRecord = PUSN_RECORD_UNION(((uint8_t*)CommonRecord) + RecordLength);
- MftBytesProcessed += RecordLength;
- }
- }
-
- const auto ElapsedMs = Timer.GetElapsedTimeMs();
-
- ZEN_INFO("MFT enumeration of {} completed after {} ({})",
- zen::NiceBytes(MftBytesProcessed),
- zen::NiceTimeSpanMs(ElapsedMs),
- zen::NiceByteRate(MftBytesProcessed, ElapsedMs));
- }
-
- // Populate by traversal
- if (m_FileSystemType == FileSystemType::ReFS)
- {
- uint64_t FileInfoBuffer[8 * 1024];
-
- FILE_INFO_BY_HANDLE_CLASS FibClass = FileIdBothDirectoryRestartInfo;
- bool Continue = true;
-
- while (Continue)
- {
- Success = GetFileInformationByHandleEx(VolumeRootDir, FibClass, FileInfoBuffer, sizeof FileInfoBuffer);
- FibClass = FileIdBothDirectoryInfo; // Set up for next iteration
-
- uint64_t EntryOffset = 0;
-
- if (!Success)
- {
- // Report failure?
-
- break;
- }
-
- do
- {
- const FILE_ID_BOTH_DIR_INFO* DirInfo =
- reinterpret_cast<const FILE_ID_BOTH_DIR_INFO*>(reinterpret_cast<const uint8_t*>(FileInfoBuffer) + EntryOffset);
-
- const uint64_t NextOffset = DirInfo->NextEntryOffset;
-
- if (NextOffset == 0)
- {
- if (EntryOffset == 0)
- {
- // First and last - end of iteration
- Continue = false;
- }
- break;
- }
-
- if (DirInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- // TODO Directory
- }
- else if (DirInfo->FileAttributes & FILE_ATTRIBUTE_DEVICE)
- {
- // TODO Device
- }
- else
- {
- // TODO File
- }
-
- EntryOffset += DirInfo->NextEntryOffset;
- } while (EntryOffset);
- }
- }
-
- // Initialize journal reading
-
- m_ReadUsnJournalData = {.StartUsn = UsnData.FirstUsn,
- .ReasonMask = USN_REASON_BASIC_INFO_CHANGE | USN_REASON_CLOSE | USN_REASON_DATA_EXTEND |
- USN_REASON_DATA_OVERWRITE | USN_REASON_DATA_TRUNCATION | USN_REASON_FILE_CREATE |
- USN_REASON_FILE_DELETE | USN_REASON_HARD_LINK_CHANGE | USN_REASON_RENAME_NEW_NAME |
- USN_REASON_RENAME_OLD_NAME | USN_REASON_REPARSE_POINT_CHANGE,
- .ReturnOnlyOnClose = true,
- .Timeout = 0,
- .BytesToWaitFor = 0,
- .UsnJournalID = UsnData.UsnJournalID,
- .MinMajorVersion = 0,
- .MaxMajorVersion = 0};
-
- return false;
-}
-
-} // namespace zen
-
-#endif // ZEN_PLATFORM_WINDOWS
diff --git a/zenserver/experimental/usnjournal.h b/zenserver/experimental/usnjournal.h
deleted file mode 100644
index 910eb7d06..000000000
--- a/zenserver/experimental/usnjournal.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#pragma once
-
-#if ZEN_PLATFORM_WINDOWS
-
-# include <zencore/windows.h>
-# include <zencore/zencore.h>
-
-ZEN_THIRD_PARTY_INCLUDES_START
-# include <winioctl.h>
-ZEN_THIRD_PARTY_INCLUDES_END
-
-# include <filesystem>
-
-namespace zen {
-
-class UsnJournalReader
-{
-public:
- UsnJournalReader();
- ~UsnJournalReader();
-
- bool Initialize(std::filesystem::path VolumePath);
-
-private:
- void* m_VolumeHandle;
- READ_USN_JOURNAL_DATA_V1 m_ReadUsnJournalData;
- bool m_IncursSeekPenalty = true;
-
- uint8_t* m_JournalReadBuffer = nullptr;
- uint64_t m_ReadBufferSize = 64 * 1024;
-
- struct Frn
- {
- uint8_t IdBytes[16];
-
- Frn() = default;
-
- Frn(const FILE_ID_128& Rhs) { memcpy(IdBytes, Rhs.Identifier, sizeof IdBytes); }
- Frn& operator=(const FILE_ID_128& Rhs) { memcpy(IdBytes, Rhs.Identifier, sizeof IdBytes); }
-
- Frn(const uint64_t& Rhs)
- {
- memcpy(IdBytes, &Rhs, sizeof Rhs);
- memset(&IdBytes[8], 0, 8);
- }
-
- Frn& operator=(const uint64_t& Rhs)
- {
- memcpy(IdBytes, &Rhs, sizeof Rhs);
- memset(&IdBytes[8], 0, 8);
- }
-
- std::strong_ordering operator<=>(const Frn&) const = default;
- };
-
- enum class FileSystemType
- {
- ReFS,
- NTFS
- };
-
- FileSystemType m_FileSystemType = FileSystemType::NTFS;
-};
-
-} // namespace zen
-
-#endif // ZEN_PLATFORM_WINDOWS
diff --git a/zenserver/experimental/vfs.cpp b/zenserver/experimental/vfs.cpp
deleted file mode 100644
index 1af9d70a7..000000000
--- a/zenserver/experimental/vfs.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#include "vfs.h"
diff --git a/zenserver/experimental/vfs.h b/zenserver/experimental/vfs.h
deleted file mode 100644
index 1aeefe481..000000000
--- a/zenserver/experimental/vfs.h
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#pragma once
-
-#include <zencore/zencore.h>
diff --git a/zenserver/testing/launch.cpp b/zenserver/testing/launch.cpp
deleted file mode 100644
index b26f9e437..000000000
--- a/zenserver/testing/launch.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#include "launch.h"
-
-#if ZEN_WITH_EXEC_SERVICES
-
-# include <zencore/compactbinary.h>
-# include <zencore/compactbinarybuilder.h>
-# include <zencore/compress.h>
-# include <zencore/filesystem.h>
-# include <zencore/fmtutils.h>
-# include <zencore/iobuffer.h>
-# include <zencore/iohash.h>
-# include <zencore/logging.h>
-# include <zencore/windows.h>
-# include <zenstore/cidstore.h>
-
-ZEN_THIRD_PARTY_INCLUDES_START
-# include <AccCtrl.h>
-# include <AclAPI.h>
-# include <UserEnv.h>
-# include <atlbase.h>
-# include <sddl.h>
-ZEN_THIRD_PARTY_INCLUDES_END
-# pragma comment(lib, "UserEnv.lib")
-
-# include <filesystem>
-# include <span>
-
-using namespace std::literals;
-
-namespace zen {
-
-struct BasicJob
-{
-public:
- BasicJob() = default;
- ~BasicJob();
-
- void SetWorkingDirectory(const std::filesystem::path& WorkingDirectory) { m_WorkingDirectory = WorkingDirectory; }
- bool SpawnJob(std::filesystem::path ExePath, std::wstring CommandLine);
- bool Wait(uint32_t TimeoutMs = ~0);
- int ExitCode();
-
-private:
- std::filesystem::path m_WorkingDirectory;
- int m_ProcessId = 0;
- CHandle m_ProcessHandle;
-};
-
-BasicJob::~BasicJob()
-{
- Wait();
-}
-
-bool
-BasicJob::SpawnJob(std::filesystem::path ExePath, std::wstring CommandLine)
-{
- STARTUPINFOEX StartupInfo = {sizeof(STARTUPINFOEX)};
- PROCESS_INFORMATION ProcessInfo{};
-
- std::wstring ExePathNative = ExePath.native();
- std::wstring WorkingDirNative = m_WorkingDirectory.native();
-
- BOOL Created = ::CreateProcess(ExePathNative.data() /* ApplicationName */,
- CommandLine.data() /* Command Line */,
- nullptr /* Process Attributes */,
- nullptr /* Security Attributes */,
- FALSE /* InheritHandles */,
- 0 /* Flags */,
- nullptr /* Environment */,
- WorkingDirNative.data() /* Current Directory */,
- (LPSTARTUPINFO)&StartupInfo,
- &ProcessInfo);
-
- if (!Created)
- {
- throw std::system_error(::GetLastError(), std::system_category(), fmt::format("Failed to create process '{}'", ExePath).c_str());
- }
-
- m_ProcessId = ProcessInfo.dwProcessId;
- m_ProcessHandle.Attach(ProcessInfo.hProcess);
- ::CloseHandle(ProcessInfo.hThread);
-
- ZEN_INFO("Created process {}", m_ProcessId);
-
- return true;
-}
-
-bool
-BasicJob::Wait(uint32_t TimeoutMs)
-{
- if (!m_ProcessHandle)
- {
- return true;
- }
-
- DWORD WaitResult = WaitForSingleObject(m_ProcessHandle, TimeoutMs);
-
- if (WaitResult == WAIT_TIMEOUT)
- {
- return false;
- }
-
- if (WaitResult == WAIT_OBJECT_0)
- {
- return true;
- }
-
- throw std::runtime_error("Failed wait on process handle");
-}
-
-int
-BasicJob::ExitCode()
-{
- DWORD Ec = 0;
- BOOL Success = GetExitCodeProcess(m_ProcessHandle, &Ec);
-
- if (!Success)
- {
- ZEN_WARN("failed getting exit code");
- }
-
- if (Ec == STILL_ACTIVE)
- {
- ZEN_WARN("getting exit code but process is STILL_ACTIVE");
- }
-
- return gsl::narrow_cast<int>(Ec);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct SandboxedJob
-{
- SandboxedJob() = default;
- ~SandboxedJob() = default;
-
- void SetWorkingDirectory(const std::filesystem::path& WorkingDirectory) { m_WorkingDirectory = WorkingDirectory; }
- void Initialize(std::string_view AppContainerId);
- bool SpawnJob(std::filesystem::path ExePath);
- void AddWhitelistFile(const std::filesystem::path& FilePath) { m_WhitelistFiles.push_back(FilePath); }
-
-private:
- bool GrantNamedObjectAccess(PWSTR Name, SE_OBJECT_TYPE Type, ACCESS_MASK AccessMask, bool Recursive);
-
- std::filesystem::path m_WorkingDirectory;
- std::vector<std::filesystem::path> m_WhitelistFiles;
- std::vector<std::wstring> m_WhitelistRegistryKeys;
- PSID m_AppContainerSid = nullptr;
- bool m_IsInitialized = false;
-};
-
-bool
-SandboxedJob::GrantNamedObjectAccess(PWSTR ObjectName, SE_OBJECT_TYPE ObjectType, ACCESS_MASK AccessMask, bool Recursive)
-{
- DWORD Status;
- PACL NewAcl = nullptr;
-
- DWORD grfInhericance = 0;
-
- if (Recursive)
- {
- grfInhericance = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
- }
-
- EXPLICIT_ACCESS Access{.grfAccessPermissions = AccessMask,
- .grfAccessMode = GRANT_ACCESS,
- .grfInheritance = grfInhericance,
- .Trustee = {.pMultipleTrustee = nullptr,
- .MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE,
- .TrusteeForm = TRUSTEE_IS_SID,
- .TrusteeType = TRUSTEE_IS_GROUP,
- .ptstrName = (PWSTR)m_AppContainerSid}};
-
- PACL OldAcl = nullptr;
-
- Status = GetNamedSecurityInfo(ObjectName /* ObjectName */,
- ObjectType /* ObjectType */,
- DACL_SECURITY_INFORMATION /* SecurityInfo */,
- nullptr /* ppsidOwner */,
- nullptr /* ppsidGroup */,
- &OldAcl /* ppDacl */,
- nullptr /* ppSacl */,
- nullptr /* ppSecurityDescriptor */);
- if (Status != ERROR_SUCCESS)
- return false;
-
- Status = SetEntriesInAcl(1 /* CountOfExplicitEntries */, &Access /* pListOfExplicitEntries */, OldAcl, &NewAcl);
- if (Status != ERROR_SUCCESS)
- return false;
-
- Status = SetNamedSecurityInfo(ObjectName /* ObjectName */,
- ObjectType /* ObjectType */,
- DACL_SECURITY_INFORMATION /*SecurityInfo */,
- nullptr /* psidOwner */,
- nullptr /* psidGroup */,
- NewAcl /* pDacl */,
- nullptr /* pSacl */);
- if (NewAcl)
- ::LocalFree(NewAcl);
-
- return Status == ERROR_SUCCESS;
-}
-
-void
-SandboxedJob::Initialize(std::string_view AppContainerId)
-{
- if (m_IsInitialized)
- {
- return;
- }
-
- std::wstring ContainerName = zen::Utf8ToWide(AppContainerId);
-
- HRESULT hRes = ::CreateAppContainerProfile(ContainerName.c_str(),
- ContainerName.c_str() /* Display Name */,
- ContainerName.c_str() /* Description */,
- nullptr /* Capabilities */,
- 0 /* Capability Count */,
- &m_AppContainerSid);
-
- if (FAILED(hRes))
- {
- hRes = ::DeriveAppContainerSidFromAppContainerName(ContainerName.c_str(), &m_AppContainerSid);
-
- if (FAILED(hRes))
- {
- ZEN_ERROR("Failed creating app container SID");
- }
- }
-
- // Debugging context
-
- PWSTR Str = nullptr;
- ::ConvertSidToStringSid(m_AppContainerSid, &Str);
-
- ZEN_INFO("AppContainer SID : '{}'", WideToUtf8(Str));
-
- PWSTR Path = nullptr;
- if (SUCCEEDED(::GetAppContainerFolderPath(Str, &Path)))
- {
- ZEN_INFO("AppContainer folder: '{}'", WideToUtf8(Path));
-
- ::CoTaskMemFree(Path);
- }
- ::LocalFree(Str);
-
- m_IsInitialized = true;
-}
-
-bool
-SandboxedJob::SpawnJob(std::filesystem::path ExePath)
-{
- // Build process attributes
-
- SECURITY_CAPABILITIES Sc = {0};
- Sc.AppContainerSid = m_AppContainerSid;
-
- STARTUPINFOEX StartupInfo = {sizeof(STARTUPINFOEX)};
- PROCESS_INFORMATION ProcessInfo{};
- SIZE_T Size = 0;
-
- ::InitializeProcThreadAttributeList(nullptr, 1, 0, &Size);
-
- auto AttrBuffer = std::make_unique<uint8_t[]>(Size);
- StartupInfo.lpAttributeList = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(AttrBuffer.get());
-
- if (!::InitializeProcThreadAttributeList(StartupInfo.lpAttributeList, 1, 0, &Size))
- {
- return false;
- }
-
- if (!::UpdateProcThreadAttribute(StartupInfo.lpAttributeList,
- 0,
- PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES,
- &Sc,
- sizeof Sc,
- nullptr,
- nullptr))
- {
- return false;
- }
-
- // Set up security for files/folders/registry
-
- for (const std::filesystem::path& File : m_WhitelistFiles)
- {
- std::wstring NativeFileName = File.native();
- GrantNamedObjectAccess(NativeFileName.data(), SE_FILE_OBJECT, FILE_ALL_ACCESS, true);
- }
-
- for (std::wstring& RegKey : m_WhitelistRegistryKeys)
- {
- GrantNamedObjectAccess(RegKey.data(), SE_REGISTRY_WOW64_32KEY, KEY_ALL_ACCESS, true);
- }
-
- std::wstring ExePathNative = ExePath.native();
- std::wstring WorkingDirNative = m_WorkingDirectory.native();
-
- BOOL Created = ::CreateProcess(nullptr /* ApplicationName */,
- ExePathNative.data() /* Command line */,
- nullptr /* Process Attributes */,
- nullptr /* Security Attributes */,
- FALSE /* InheritHandles */,
- EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE /* Flags */,
- nullptr /* Environment */,
- WorkingDirNative.data() /* Current Directory */,
- (LPSTARTUPINFO)&StartupInfo,
- &ProcessInfo);
-
- DeleteProcThreadAttributeList(StartupInfo.lpAttributeList);
-
- if (!Created)
- {
- return false;
- }
-
- ZEN_INFO("Created process {}", ProcessInfo.dwProcessId);
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-HttpLaunchService::HttpLaunchService(CidStore& Store, const std::filesystem::path& SandboxBaseDir)
-: m_Log(logging::Get("exec"))
-, m_CidStore(Store)
-, m_SandboxPath(SandboxBaseDir)
-{
- m_Router.AddPattern("job", "([[:digit:]]+)");
-
- m_Router.RegisterRoute(
- "jobs/{job}",
- [this](HttpRouterRequest& Req) {
- HttpServerRequest& HttpReq = Req.ServerRequest();
-
- switch (HttpReq.RequestVerb())
- {
- case HttpVerb::kGet:
- break;
-
- case HttpVerb::kPost:
- break;
-
- default:
- break;
- }
- },
- HttpVerb::kGet | HttpVerb::kPost);
-
- // Experimental
-
-# if 0
- m_Router.RegisterRoute(
- "jobs/sandbox",
- [this](HttpRouterRequest& Req) {
- HttpServerRequest& HttpReq = Req.ServerRequest();
-
- switch (HttpReq.RequestVerb())
- {
- case HttpVerb::kGet:
- break;
-
- case HttpVerb::kPost:
- {
- SandboxedJob Job;
- Job.Initialize("zen_test");
- Job.SetWorkingDirectory("c:\\temp\\sandbox1");
- Job.AddWhitelistFile("c:\\temp\\sandbox1");
- Job.SpawnJob("c:\\windows\\system32\\cmd.exe");
- }
- break;
-
- default:
- break;
- }
- },
- HttpVerb::kGet | HttpVerb::kPost);
-# endif
-
- m_Router.RegisterRoute(
- "jobs/prep",
- [this](HttpRouterRequest& Req) {
- HttpServerRequest& HttpReq = Req.ServerRequest();
-
- switch (HttpReq.RequestVerb())
- {
- case HttpVerb::kPost:
- {
- // This operation takes the proposed job spec and identifies which
- // chunks are not present on this server. This list is then returned in
- // the "need" list in the response
-
- IoBuffer Payload = HttpReq.ReadPayload();
- CbObject RequestObject = LoadCompactBinaryObject(Payload);
-
- std::vector<IoHash> NeedList;
-
- for (auto Entry : RequestObject["files"sv])
- {
- CbObjectView Ob = Entry.AsObjectView();
-
- const IoHash FileHash = Ob["hash"sv].AsHash();
-
- if (!m_CidStore.FindChunkByCid(FileHash))
- {
- ZEN_DEBUG("NEED: {} {} {}", FileHash, Ob["file"sv].AsString(), Ob["size"sv].AsUInt64());
-
- NeedList.push_back(FileHash);
- }
- }
-
- CbObjectWriter Cbo;
- Cbo.BeginArray("need");
-
- for (const IoHash& Hash : NeedList)
- {
- Cbo << Hash;
- }
-
- Cbo.EndArray();
- CbObject Response = Cbo.Save();
-
- return HttpReq.WriteResponse(HttpResponseCode::OK, Response);
- }
- break;
-
- default:
- break;
- }
- },
- HttpVerb::kPost);
-
- m_Router.RegisterRoute(
- "jobs",
- [this](HttpRouterRequest& Req) {
- HttpServerRequest& HttpReq = Req.ServerRequest();
-
- switch (HttpReq.RequestVerb())
- {
- case HttpVerb::kGet:
- break;
-
- case HttpVerb::kPost:
- {
- IoBuffer Payload = HttpReq.ReadPayload();
- CbObject RequestObject = LoadCompactBinaryObject(Payload);
-
- bool AllOk = true;
-
- std::vector<IoHash> NeedList;
-
- std::filesystem::path SandboxDir{CreateNewSandbox()};
-
- ZEN_DEBUG("setting up job in sandbox '{}'", SandboxDir);
-
- zen::DeleteDirectories(SandboxDir);
- zen::CreateDirectories(SandboxDir);
-
- for (auto Entry : RequestObject["files"sv])
- {
- CbObjectView Ob = Entry.AsObjectView();
-
- std::string_view FileName = Ob["file"sv].AsString();
- const IoHash FileHash = Ob["hash"sv].AsHash();
- uint64_t FileSize = Ob["size"sv].AsUInt64();
-
- if (IoBuffer Chunk = m_CidStore.FindChunkByCid(FileHash); !Chunk)
- {
- ZEN_DEBUG("MISSING: {} {} {}", FileHash, FileName, FileSize);
- AllOk = false;
-
- NeedList.push_back(FileHash);
- }
- else
- {
- std::filesystem::path FullPath = SandboxDir / FileName;
-
- IoHash RawHash;
- uint64_t RawSize;
- CompressedBuffer Compressed = CompressedBuffer::FromCompressed(SharedBuffer(Chunk), RawHash, RawSize);
- ZEN_ASSERT(Compressed);
- ZEN_ASSERT(FileHash == RawHash);
- CompositeBuffer CompositeBuffer = Compressed.DecompressToComposite();
- std::span<const SharedBuffer> Segments = CompositeBuffer.GetSegments();
- std::vector<IoBuffer> Chunks(Segments.size());
- std::vector<IoBuffer*> ChunkPtrs(Segments.size());
- for (size_t Index = 0; Index < Segments.size(); ++Index)
- {
- Chunks[Index] = std::move(Segments[Index].AsIoBuffer());
- ChunkPtrs[Index] = &Chunks[Index];
- }
-
- zen::WriteFile(FullPath, ChunkPtrs.data(), ChunkPtrs.size());
- }
- }
-
- if (!AllOk)
- {
- // TODO: Could report all the missing pieces in the response here
- return HttpReq.WriteResponse(HttpResponseCode::NotFound);
- }
-
- std::string Executable8{RequestObject["cmd"].AsString()};
- std::string Args8{RequestObject["args"].AsString()};
-
- std::wstring Executable = Utf8ToWide(Executable8);
- std::wstring Args = Utf8ToWide(Args8);
-
- ZEN_DEBUG("spawning job in sandbox '{}': '{}' '{}'", SandboxDir, Executable8, Args8);
-
- std::filesystem::path ExeName = SandboxDir / Executable;
-
- BasicJob Job;
- Job.SetWorkingDirectory(SandboxDir);
- Job.SpawnJob(ExeName, Args);
- Job.Wait();
-
- CbObjectWriter Response;
-
- Response << "exitcode" << Job.ExitCode();
-
- return HttpReq.WriteResponse(HttpResponseCode::OK, Response.Save());
- }
- break;
-
- default:
- break;
- }
- },
- HttpVerb::kGet | HttpVerb::kPost);
-}
-
-HttpLaunchService::~HttpLaunchService()
-{
-}
-
-const char*
-HttpLaunchService::BaseUri() const
-{
- return "/exec/";
-}
-
-void
-HttpLaunchService::HandleRequest(HttpServerRequest& Request)
-{
- if (m_Router.HandleRequest(Request) == false)
- {
- ZEN_WARN("No route found for {0}", Request.RelativeUri());
- }
-}
-
-std::filesystem::path
-HttpLaunchService::CreateNewSandbox()
-{
- std::string UniqueId = std::to_string(++m_SandboxCount);
- std::filesystem::path Path = m_SandboxPath / UniqueId;
- zen::CreateDirectories(Path);
- return Path;
-}
-
-} // namespace zen
-
-#endif // ZEN_WITH_EXEC_SERVICES
diff --git a/zenserver/testing/launch.h b/zenserver/testing/launch.h
deleted file mode 100644
index f44618bfb..000000000
--- a/zenserver/testing/launch.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#pragma once
-
-#include <zencore/zencore.h>
-
-#if !defined(ZEN_WITH_EXEC_SERVICES)
-# define ZEN_WITH_EXEC_SERVICES ZEN_PLATFORM_WINDOWS
-#endif
-
-#if ZEN_WITH_EXEC_SERVICES
-
-# include <zencore/logging.h>
-# include <zenhttp/httpserver.h>
-
-# include <filesystem>
-
-namespace zen {
-
-class CidStore;
-
-/**
- * Process launcher for test executables
- */
-class HttpLaunchService : public HttpService
-{
-public:
- HttpLaunchService(CidStore& Store, const std::filesystem::path& SandboxBaseDir);
- ~HttpLaunchService();
-
- virtual const char* BaseUri() const override;
- virtual void HandleRequest(HttpServerRequest& Request) override;
-
-private:
- inline spdlog::logger& Log() { return m_Log; }
-
- spdlog::logger& m_Log;
- HttpRequestRouter m_Router;
- CidStore& m_CidStore;
- std::filesystem::path m_SandboxPath;
- std::atomic<int> m_SandboxCount{0};
-
- std::filesystem::path CreateNewSandbox();
-};
-
-} // namespace zen
-
-#endif // ZEN_WITH_EXEC_SERVICES
diff --git a/zenserver/xmake.lua b/zenserver/xmake.lua
index 2174ad679..8b18bf9f9 100644
--- a/zenserver/xmake.lua
+++ b/zenserver/xmake.lua
@@ -16,6 +16,7 @@ target("zenserver")
add_ldflags("/subsystem:console,5.02")
add_ldflags("/MANIFEST:EMBED")
add_ldflags("/LTCG")
+ add_files("zenserver.rc")
else
remove_files("windows/**")
end
@@ -30,7 +31,6 @@ target("zenserver")
add_syslinks("bsm")
end
- add_options("vfs")
add_options("compute")
add_options("exec")
diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp
index c1e82f404..526e27152 100644
--- a/zenserver/zenserver.cpp
+++ b/zenserver/zenserver.cpp
@@ -105,13 +105,11 @@ ZEN_THIRD_PARTY_INCLUDES_END
#include "cidstore.h"
#include "compute/function.h"
#include "diag/diagsvcs.h"
-#include "experimental/usnjournal.h"
#include "frontend/frontend.h"
#include "monitoring/httpstats.h"
#include "monitoring/httpstatus.h"
#include "projectstore.h"
#include "testing/httptest.h"
-#include "testing/launch.h"
#include "upstream/upstream.h"
#include "zenstore/gc.h"
@@ -266,23 +264,6 @@ public:
m_ProjectStore = new zen::ProjectStore(*m_CidStore, m_DataRoot / "projects", m_GcManager);
m_HttpProjectService.reset(new zen::HttpProjectService{*m_CidStore, m_ProjectStore});
-#if ZEN_WITH_EXEC_SERVICES
-
- if (ServerOptions.ExecServiceEnabled)
- {
- ZEN_INFO("instantiating exec service");
-
- std::filesystem::path SandboxDir = m_DataRoot / "exec" / "sandbox";
- zen::CreateDirectories(SandboxDir);
- m_HttpLaunchService = std::make_unique<zen::HttpLaunchService>(*m_CidStore, SandboxDir);
- }
- else
- {
- ZEN_INFO("NOT instantiating exec services");
- }
-
-#endif // ZEN_WITH_EXEC_SERVICES
-
#if ZEN_WITH_COMPUTE_SERVICES
if (ServerOptions.ComputeServiceEnabled)
{
@@ -319,15 +300,6 @@ public:
m_Http->RegisterService(*m_CidService);
-#if ZEN_WITH_EXEC_SERVICES
- if (ServerOptions.ExecServiceEnabled)
- {
- if (m_HttpLaunchService != nullptr)
- {
- m_Http->RegisterService(*m_HttpLaunchService);
- }
- }
-#endif // ZEN_WITH_EXEC_SERVICES
#if ZEN_WITH_COMPUTE_SERVICES
if (ServerOptions.ComputeServiceEnabled)
{
@@ -592,9 +564,6 @@ private:
std::unique_ptr<zen::HttpStructuredCacheService> m_StructuredCacheService;
zen::HttpAdminService m_AdminService{m_GcScheduler};
zen::HttpHealthService m_HealthService;
-#if ZEN_WITH_EXEC_SERVICES
- std::unique_ptr<zen::HttpLaunchService> m_HttpLaunchService;
-#endif // ZEN_WITH_EXEC_SERVICES
#if ZEN_WITH_COMPUTE_SERVICES
std::unique_ptr<zen::HttpFunctionService> m_HttpFunctionService;
#endif // ZEN_WITH_COMPUTE_SERVICES
diff --git a/zenserver/zenserver.rc b/zenserver/zenserver.rc
index c063436ef..6d31e2c6e 100644
--- a/zenserver/zenserver.rc
+++ b/zenserver/zenserver.rc
@@ -2,6 +2,8 @@
//
#include "resource.h"
+#include "zencore/config.h"
+
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
@@ -79,3 +81,25 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION ZEN_CFG_VERSION_MAJOR,ZEN_CFG_VERSION_MINOR,ZEN_CFG_VERSION_ALTER,0
+PRODUCTVERSION ZEN_CFG_VERSION_MAJOR,ZEN_CFG_VERSION_MINOR,ZEN_CFG_VERSION_ALTER,0
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904b0"
+ {
+ VALUE "CompanyName", "Epic Games Inc\0"
+ VALUE "FileDescription", "Local Storage Service for Unreal Engine\0"
+ VALUE "FileVersion", ZEN_CFG_VERSION "\0"
+ VALUE "LegalCopyright", "Copyright Epic Games Inc. All Rights Reserved\0"
+ VALUE "OriginalFilename", "zenserver.exe\0"
+ VALUE "ProductName", "Zen Storage Server\0"
+ VALUE "ProductVersion", ZEN_CFG_VERSION_BUILD_STRING_FULL "\0"
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x409, 1200
+ }
+}