Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* text=auto eol=lf
*.bat text eol=crlf
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
!/res
!/platform
!/.github
!/packager

!.gitignore
!.gitattributes
!*.cpp
!*.h
!*.sln
Expand All @@ -14,6 +16,7 @@
!*.ico
!*.rc
!*.manifest
!packages.config

!LICENSE
!build.gradle
2 changes: 1 addition & 1 deletion fabric-installer-native-bootstrap.rc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#include "src\resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
Expand Down
16 changes: 10 additions & 6 deletions fabric-installer-native-bootstrap.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,32 @@ VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fabric-installer-native-bootstrap", "fabric-installer-native-bootstrap.vcxproj", "{B900FD00-808B-4A95-B40B-9B243B186FF0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packager", "packager\packager.vcxproj", "{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|ARM64.Build.0 = Debug|ARM64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|Win32.ActiveCfg = Debug|Win32
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|Win32.Build.0 = Debug|Win32
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|x64.ActiveCfg = Debug|x64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Debug|x64.Build.0 = Debug|x64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|ARM64.ActiveCfg = Release|ARM64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|ARM64.Build.0 = Release|ARM64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|Win32.ActiveCfg = Release|Win32
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|Win32.Build.0 = Release|Win32
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|x64.ActiveCfg = Release|x64
{B900FD00-808B-4A95-B40B-9B243B186FF0}.Release|x64.Build.0 = Release|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Debug|ARM64.ActiveCfg = Debug|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Debug|ARM64.Build.0 = Debug|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Debug|x64.ActiveCfg = Debug|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Debug|x64.Build.0 = Debug|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Release|ARM64.ActiveCfg = Release|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Release|ARM64.Build.0 = Release|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Release|x64.ActiveCfg = Release|x64
{A3999EF4-14BF-4910-A6AB-13FB5730F7E6}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
38 changes: 31 additions & 7 deletions fabric-installer-native-bootstrap.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,13 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ControlFlowGuard>false</ControlFlowGuard>
<EnablePREfast>true</EnablePREfast>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -154,10 +156,12 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ControlFlowGuard>Guard</ControlFlowGuard>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -176,11 +180,13 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ControlFlowGuard>false</ControlFlowGuard>
<EnablePREfast>true</EnablePREfast>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -197,11 +203,13 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ControlFlowGuard>false</ControlFlowGuard>
<EnablePREfast>true</EnablePREfast>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -221,9 +229,11 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<ControlFlowGuard>Guard</ControlFlowGuard>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -245,9 +255,11 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<ControlFlowGuard>Guard</ControlFlowGuard>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -261,17 +273,19 @@
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\EmbeddedResource.cpp" />
<ClCompile Include="src\Architecture.cpp" />
<ClCompile Include="src\Bootstrap.cpp" />
<ClCompile Include="src\Logger.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\SystemHelper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\EmbeddedResource.h" />
<ClInclude Include="src\Architecture.h" />
<ClInclude Include="src\Bootstrap.h" />
<ClInclude Include="src\ISystemHelper.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="src\resource.h" />
<ClInclude Include="src\Logger.h" />
<ClInclude Include="src\SystemHelper.h" />
</ItemGroup>
Expand All @@ -281,7 +295,17 @@
<ItemGroup>
<Image Include="icon.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>
21 changes: 20 additions & 1 deletion fabric-installer-native-bootstrap.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
<ClCompile Include="src\Logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Architecture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\EmbeddedResource.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Bootstrap.h">
Expand All @@ -38,12 +44,18 @@
<ClInclude Include="src\SystemHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<ClInclude Include="src\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Logger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Architecture.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\EmbeddedResource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="fabric-installer-native-bootstrap.rc">
Expand All @@ -55,4 +67,11 @@
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natstepfilter" />
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions packager/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*

!.gitignore
!*.cpp
!*.h
!*.sln
!*.vcxproj
!*.filters
!packages.config
80 changes: 80 additions & 0 deletions packager/packager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <print>
#include <filesystem>
#include <fstream>
#include <wil/resource.h>
#include <Windows.h>

namespace {
constexpr auto IDI_EMBEDDED_JAR = 201;
Copy link

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resource ID constant IDI_EMBEDDED_JAR is duplicated. It should be defined in the shared resource.h file and included here to avoid magic numbers and maintain consistency.

Copilot uses AI. Check for mistakes.

std::vector<char> readFile(const std::filesystem::path& path) {
wil::unique_hfile file{
::CreateFileW(
path.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
)
};
THROW_LAST_ERROR_IF_MSG(!file, "CreateFileW");

LARGE_INTEGER fileSize{};
THROW_LAST_ERROR_IF(::GetFileSizeEx(file.get(), &fileSize) == 0);
THROW_WIN32_IF(ERROR_FILE_TOO_LARGE, fileSize.QuadPart > SIZE_MAX);

std::vector<char> buffer(static_cast<size_t>(fileSize.QuadPart));
DWORD bytesRead = 0;
THROW_LAST_ERROR_IF(!::ReadFile(file.get(), buffer.data(), static_cast<DWORD>(buffer.size()), &bytesRead, nullptr));
THROW_WIN32_IF(ERROR_HANDLE_EOF, bytesRead != buffer.size());

return buffer;
}

void updateResource(const std::filesystem::path& exe, const std::vector<char>& data, WORD resourceId) {
HANDLE handle = THROW_LAST_ERROR_IF_NULL(::BeginUpdateResourceW(exe.c_str(), false));

bool success = false;
auto _ = wil::scope_exit([&]() noexcept { ::EndUpdateResourceW(handle, !success); });

auto intResource{ MAKEINTRESOURCE(resourceId) };
THROW_LAST_ERROR_IF(!::UpdateResourceW(handle, RT_RCDATA, intResource, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPVOID)data.data(), static_cast<DWORD>(data.size())));

success = true;
}

void packageInstaller(const std::filesystem::path& bootstrap, std::filesystem::path& installer) {
THROW_WIN32_IF_MSG(ERROR_FILE_NOT_FOUND, !std::filesystem::exists(bootstrap), "Boostrap not found");
THROW_WIN32_IF_MSG(ERROR_FILE_NOT_FOUND, !std::filesystem::exists(installer), "Installer not found");

auto installerBytes = readFile(installer);
updateResource(bootstrap, installerBytes, IDI_EMBEDDED_JAR);

std::print("Done, {} updated to embed {}\n", bootstrap.string(), installer.string());
}
}

int wmain(int argc, wchar_t* argv[])
{
if (argc != 3) {
std::print("Usage: packager <bootstrap_exe> <embedded_installer>\n");
return 1;
}

std::filesystem::path bootstrap{ argv[1] };
std::filesystem::path installer{ argv[2] };

std::print("Packager: {} Installer: {}\n", bootstrap.string(), installer.string());

try {
packageInstaller(bootstrap, installer);
}
catch (const std::exception& error) {
std::print("Packager failed: {}\n", error.what());
throw;
}

return 0;
}
Loading
Loading