Add ARM64 support (#641)

* Add ARM64 build configurations to projects

* StartMenu: add ARM64 support

* Add support for IAT hooking on ARM64

* Add ARM64 support to Classic IE

* Add ARM64 support to installer

NB: WiX 3.14.0.3910 or higher is required to create the MSI

* Revert whitespace change

* Separate x86/x64 and ARM64 installers

* Change suffix of ARM64 binaries

* Put also ARM64 MSI to final installer

* Fix sln

* Build some DLLs as ARM64X

These are meant to be loaded to both x64 and ARM64 processes.
We will compile them as ARM64X (when building for ARM64).
That way they will contain both x64 and ARM64 code paths.

https://learn.microsoft.com/en-us/windows/arm/arm64x-pe

* Make sure x64 installer cannot be installed on ARM64

In case if somebody manually tries to install x64 MSI on ARM64.
This is not supported/working scenario.

---------

Co-authored-by: ge0rdi <ge0rdi@users.noreply.github.com>
This commit is contained in:
Matthijs Lavrijsen
2025-05-08 10:14:56 +02:00
committed by GitHub
parent 146c27ecd2
commit 58b909037f
25 changed files with 636 additions and 48 deletions

View File

@@ -86,7 +86,7 @@ int CalcMsiChecksum( wchar_t *const *params, int count )
// load files
wchar_t path1[_MAX_PATH];
std::vector<unsigned char> buf1, buf2;
std::vector<unsigned char> buf1, buf2, buf3;
Sprintf(path1,_countof(path1),L"%s\\Setup32.msi",params[1]);
LoadFile(path1,buf1);
if (buf1.empty())
@@ -102,20 +102,30 @@ int CalcMsiChecksum( wchar_t *const *params, int count )
Printf("Failed to open file %s\n",path2);
return 1;
}
wchar_t path3[_MAX_PATH];
Sprintf(path3,_countof(path3),L"%s\\SetupARM64.msi",params[1]);
LoadFile(path3,buf3);
if (buf3.empty())
{
Printf("Failed to open file %s\n",path3);
return 1;
}
int len1=(int)buf1.size();
int len2=(int)buf2.size();
int len3=(int)buf3.size();
for (std::vector<unsigned char>::iterator it=buf1.begin();it!=buf1.end();++it)
*it^=0xFF;
for (std::vector<unsigned char>::iterator it=buf2.begin();it!=buf2.end();++it)
*it^=0xFF;
for (std::vector<unsigned char>::iterator it=buf3.begin();it!=buf3.end();++it)
*it^=0xFF;
// detect common blocks (assuming at least 256K in size and in the same order in both files)
const int BLOCK_SIZE=256*1024;
const int BLOCK_SIZE = 256 * 1024;
// detect x86/x64 common blocks (assuming at least 256K in size and in the same order in both files)
std::vector<Chunk> chunks;
int start2=0;
for (int i=0;i<len1-BLOCK_SIZE;i+=BLOCK_SIZE)
for (int i=0,start2=0;i<len1-BLOCK_SIZE;i+=BLOCK_SIZE)
{
for (int j=start2;j<len2-BLOCK_SIZE;j++)
{
@@ -142,6 +152,35 @@ int CalcMsiChecksum( wchar_t *const *params, int count )
}
}
}
// detect x86/ARM64 common blocks (assuming at least 256K in size and in the same order in both files)
std::vector<Chunk> chunks2;
for (int i=0,start2=0;i<len1-BLOCK_SIZE;i+=BLOCK_SIZE)
{
for (int j=start2;j<len3-BLOCK_SIZE;j++)
{
if (memcmp(&buf1[i],&buf3[j],BLOCK_SIZE)==0)
{
Chunk chunk;
chunk.start1=i;
chunk.start2=j;
chunk.len=BLOCK_SIZE;
while (chunk.start1>0 && chunk.start2>0 && buf1[chunk.start1-1]==buf3[chunk.start2-1])
{
chunk.start1--;
chunk.start2--;
chunk.len++;
}
while (chunk.start1+chunk.len<len1 && chunk.start2+chunk.len<len3 && buf1[chunk.start1+chunk.len]==buf3[chunk.start2+chunk.len])
{
chunk.len++;
}
chunks2.push_back(chunk);
i=chunk.start1+chunk.len-1;
start2=chunk.start2+chunk.len;
break;
}
}
}
// save modified 32-bit MSI
{
@@ -177,9 +216,31 @@ int CalcMsiChecksum( wchar_t *const *params, int count )
fclose(f);
}
unsigned int fnvs[2];
// save modified ARM64 MSI
{
Strcat(path3,_countof(path3),L"_");
FILE* f=NULL;
if (_wfopen_s(&f,path3,L"wb") || !f)
{
Printf("Failed to write %s\n",path3);
return 1;
}
int start=0;
for (std::vector<Chunk>::const_iterator it=chunks2.begin();it!=chunks2.end();++it)
{
if (it->start2-start>0)
fwrite(&buf3[start],1,it->start2-start,f);
start=it->start2+it->len;
}
if (len3-start>0)
fwrite(&buf3[start],1,len3-start,f);
fclose(f);
}
unsigned int fnvs[3];
fnvs[0]=CalcFNVHash(&buf1[0],len1,FNV_HASH0);
fnvs[1]=CalcFNVHash(&buf2[0],len2,FNV_HASH0);
fnvs[2]=CalcFNVHash(&buf3[0],len3,FNV_HASH0);
// save fnvs and chunks
{
@@ -193,6 +254,9 @@ int CalcMsiChecksum( wchar_t *const *params, int count )
int count=(int)chunks.size();
fwrite(&count,1,4,f);
fwrite(&chunks[0],sizeof(Chunk),count,f);
count=(int)chunks2.size();
fwrite(&count,1,4,f);
fwrite(&chunks2[0],sizeof(Chunk),count,f);
fclose(f);
}
return 0;
@@ -841,7 +905,7 @@ static HRESULT CALLBACK TaskDialogCallback( HWND hwnd, UINT uNotification, WPARA
// Open-Shell utility - multiple utilities for building and maintaining Open-Shell
// Usage:
// no parameters - saves a troubleshooting log
// crcmsi <msi path> // creates a file with checksum of both msi files
// crcmsi <msi path> // creates a file with checksum of all msi files
// makeEN <explorer dll> <start menu dll> <ie dll> <update exe> // extracts the localization resources and creates a sample en-US.DLL
// extract <dll> <csv> // extracts the string table, the dialog text, and the L10N text from a DLL and stores it in a CSV
// extract en-us.dll <dll> <csv> // extracts the string table, the dialog text, and the L10N text from two DLL and stores it in a CSV

View File

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
@@ -9,6 +13,10 @@
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@@ -63,6 +71,7 @@
<ItemGroup>
<ResourceCompile Include="Utility.rc">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
</ResourceCompile>
</ItemGroup>
<ItemGroup>