diff --git a/Installer/package.txt b/Installer/package.txt
index 0500cf6e3fe..519931b61fe 100644
--- a/Installer/package.txt
+++ b/Installer/package.txt
@@ -42,6 +42,12 @@ installer LiveCode
include Externals
with TargetFolder as [[ToolsFolder]]/Runtime/Windows/x86-32 do
set TargetPlatform to Windows
+ set TargetArchitecture to x86
+ include Runtime
+ include Externals
+ with TargetFolder as [[ToolsFolder]]/Runtime/Windows/x86-64 do
+ set TargetPlatform to Windows
+ set TargetArchitecture to x86_64
include Runtime
include Externals
with TargetFolder as [[ToolsFolder]]/Runtime/Linux/x86-32 do
@@ -492,10 +498,10 @@ component Toolchain.MacOSX
component Toolchain.Windows
into [[ToolsFolder]]/Toolchain place
- executable windows:lc-compile.exe as lc-compile.exe
- executable windows:lc-run.exe as lc-run.exe
- executable windows:lc-compile-ffi-java.exe as lc-compile-ffi-java.exe
- rfolder windows:modules
+ executable win-[[TargetArchitecture]]:lc-compile.exe as lc-compile.exe
+ executable win-[[TargetArchitecture]]:lc-run.exe as lc-run.exe
+ executable win-[[TargetArchitecture]]:lc-compile-ffi-java.exe as lc-compile-ffi-java.exe
+ rfolder win-[[TargetArchitecture]]:modules
component Toolchain.Linux
into [[ToolsFolder]]/Toolchain place
@@ -520,13 +526,13 @@ component Mobile.Linux
component Engine.Windows
into [[TargetFolder]] place
- executable windows:LiveCode[[EditionTagUpper]].exe as [[ProductName]].exe
- executable windows:revpdfprinter.dll
- executable windows:revsecurity.dll
+ executable win-[[TargetArchitecture]]:LiveCode[[EditionTagUpper]].exe as [[ProductName]].exe
+ executable win-[[TargetArchitecture]]:revpdfprinter.dll
+ executable win-[[TargetArchitecture]]:revsecurity.dll
component Mobile.Windows
into "[[ToolsFolder]]/Externals" place
- executable windows:revandroid.dll
+ executable win-[[TargetArchitecture]]:revandroid.dll
//////////
@@ -571,13 +577,13 @@ component Runtime.Linux
component Runtime.Windows
into [[TargetFolder]] place
- executable windows:standalone[[BaseEditionTagLower]].exe as Standalone
- file "windows:w32-manifest-template.xml"
- file "windows:w32-manifest-template-dpiaware.xml"
- file "windows:w32-manifest-template-trustinfo.xml"
+ executable win-[[TargetArchitecture]]:standalone[[BaseEditionTagLower]].exe as Standalone
+ file "win-[[TargetArchitecture]]:w32-manifest-template.xml"
+ file "win-[[TargetArchitecture]]:w32-manifest-template-dpiaware.xml"
+ file "win-[[TargetArchitecture]]:w32-manifest-template-trustinfo.xml"
into [[TargetFolder]]/Support place
- executable windows:revpdfprinter.dll
- executable windows:revsecurity.dll
+ executable win-[[TargetArchitecture]]:revpdfprinter.dll
+ executable win-[[TargetArchitecture]]:revsecurity.dll
into "[[TargetFolder]]/Support/Sample Icons" place
file "ide:Resources/Sample Icons/genericapp.ico"
file "ide:Resources/Sample Icons/genericdoc.ico"
@@ -812,10 +818,10 @@ component Externals.Linux
component Externals.Windows
into [[TargetFolder]]/Externals place
- executable windows:revspeech.dll
- executable windows:revxml.dll
- executable windows:revbrowser.dll
- executable windows:revzip.dll
+ executable win-[[TargetArchitecture]]:revspeech.dll
+ executable win-[[TargetArchitecture]]:revxml.dll
+ executable win-[[TargetArchitecture]]:revbrowser.dll
+ executable win-[[TargetArchitecture]]:revzip.dll
declare external "Speech" using revspeech.dll
declare external "XML" using revxml.dll
declare external "Browser" using revbrowser.dll
@@ -856,26 +862,26 @@ component Externals.CEF.Linux
component Externals.CEF.Windows
into [[TargetFolder]]/Externals/CEF place
- executable windows:libbrowser-cefprocess.exe
- executable windows:revbrowser-cefprocess.exe
- executable windows:Externals/CEF/libcef.dll
- executable windows:Externals/CEF/d3dcompiler_43.dll
- executable windows:Externals/CEF/d3dcompiler_47.dll
- executable windows:Externals/CEF/libEGL.dll
- executable windows:Externals/CEF/libGLESv2.dll
- executable windows:Externals/CEF/chrome_elf.dll
- rfolder windows:Externals/CEF/locales
- file windows:Externals/CEF/cef.pak
- file windows:Externals/CEF/cef_100_percent.pak
- file windows:Externals/CEF/cef_200_percent.pak
- file windows:Externals/CEF/cef_extensions.pak
- file windows:Externals/CEF/icudtl.dat
- file windows:Externals/CEF/natives_blob.bin
- file windows:Externals/CEF/snapshot_blob.bin
- file windows:Externals/CEF/v8_context_snapshot.bin
+ executable win-[[TargetArchitecture]]:libbrowser-cefprocess.exe
+ executable win-[[TargetArchitecture]]:revbrowser-cefprocess.exe
+ executable win-[[TargetArchitecture]]:Externals/CEF/libcef.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/d3dcompiler_43.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/d3dcompiler_47.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/libEGL.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/libGLESv2.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/chrome_elf.dll
+ rfolder win-[[TargetArchitecture]]:Externals/CEF/locales
+ file win-[[TargetArchitecture]]:Externals/CEF/cef.pak
+ file win-[[TargetArchitecture]]:Externals/CEF/cef_100_percent.pak
+ file win-[[TargetArchitecture]]:Externals/CEF/cef_200_percent.pak
+ file win-[[TargetArchitecture]]:Externals/CEF/cef_extensions.pak
+ file win-[[TargetArchitecture]]:Externals/CEF/icudtl.dat
+ file win-[[TargetArchitecture]]:Externals/CEF/natives_blob.bin
+ file win-[[TargetArchitecture]]:Externals/CEF/snapshot_blob.bin
+ file win-[[TargetArchitecture]]:Externals/CEF/v8_context_snapshot.bin
into [[TargetFolder]]/Externals/CEF/swiftshader place
- executable windows:Externals/CEF/swiftshader/libEGL.dll
- executable windows:Externals/CEF/swiftshader/libGLESv2.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/swiftshader/libEGL.dll
+ executable win-[[TargetArchitecture]]:Externals/CEF/swiftshader/libGLESv2.dll
////////////////////////////////////////////////////////////////////////////////
@@ -897,12 +903,12 @@ component Databases.Linux
component Databases.Windows
into "[[TargetFolder]]/Externals" place
- executable windows:revdb.dll
+ executable win-[[TargetArchitecture]]:revdb.dll
into "[[TargetFolder]]/Externals/Database Drivers" place
- executable windows:dbmysql.dll
- executable windows:dbodbc.dll
- executable windows:dbpostgresql.dll
- executable windows:dbsqlite.dll
+ executable win-[[TargetArchitecture]]:dbmysql.dll
+ executable win-[[TargetArchitecture]]:dbodbc.dll
+ executable win-[[TargetArchitecture]]:dbpostgresql.dll
+ executable win-[[TargetArchitecture]]:dbsqlite.dll
declare external "Database" using revdb.dll
declare dbdriver "MySQL" using dbmysql.dll
declare dbdriver "ODBC" using dbodbc.dll
@@ -977,7 +983,9 @@ component TimeZone
into [[ToolsFolder]]/Extensions/com.livecode.library.timezone place
rfolder ios:iphoneos12.1/packaged_extensions/com.livecode.library.timezone/code
into [[ToolsFolder]]/Extensions/com.livecode.library.timezone place
- rfolder windows:packaged_extensions/com.livecode.library.timezone/code
+ rfolder win-x86:packaged_extensions/com.livecode.library.timezone/code
+ into [[ToolsFolder]]/Extensions/com.livecode.library.timezone place
+ rfolder win-x86_64:packaged_extensions/com.livecode.library.timezone/code
into [[ToolsFolder]]/Extensions/com.livecode.library.timezone place
rfolder linux-x86_64:packaged_extensions/com.livecode.library.timezone/code
into [[ToolsFolder]]/Extensions/com.livecode.library.timezone place
diff --git a/buildbot.mk b/buildbot.mk
index d7c37f8a371..93c1635d0ef 100644
--- a/buildbot.mk
+++ b/buildbot.mk
@@ -191,11 +191,13 @@ distmac-bundle-business:
dist-upload-files.txt sha1sum.txt:
set -e; \
find . -maxdepth 1 -name 'LiveCode*-*-Mac.dmg' \
- -o -name 'LiveCode*Installer-*-Windows.exe' \
+ -o -name 'LiveCode*Installer-*-Windows-x86.exe' \
+ -o -name 'LiveCode*Installer-*-Windows-x86_64.exe' \
-o -name 'LiveCode*Installer-*-Linux.*' \
-o -name 'LiveCode*Server-*-Linux*.zip' \
-o -name 'LiveCode*Server-*-Mac.zip' \
- -o -name 'LiveCode*Server-*-Windows.zip' \
+ -o -name 'LiveCode*Server-*-Windows-x86.zip' \
+ -o -name 'LiveCode*Server-*-Windows-x86_64.zip' \
-o -name 'LiveCode*Docs-*.zip' \
-o -name '*-bin.tar.xz' \
-o -name '*-bin.tar.bz2' \
diff --git a/builder/builder_tool.livecodescript b/builder/builder_tool.livecodescript
index e5b245f71d3..007f932ab1b 100644
--- a/builder/builder_tool.livecodescript
+++ b/builder/builder_tool.livecodescript
@@ -44,8 +44,10 @@ on startup
if it is "linux" then
put true into tPlatforms["linux-x86"]
put true into tPlatforms["linux-x86_64"]
+ else if it is "win" then
+ put true into tPlatforms["win-x86"]
+ put true into tPlatforms["win-x86_64"]
else
- if it begins with "win" then get "windows"
if it is "mac" then get "macosx"
put true into tPlatforms[it]
end if
diff --git a/builder/builder_utilities.livecodescript b/builder/builder_utilities.livecodescript
index 69215f8b3ff..a61b6544f99 100644
--- a/builder/builder_utilities.livecodescript
+++ b/builder/builder_utilities.livecodescript
@@ -133,7 +133,13 @@ function builderPlatform
end if
throw "Unknown Linux architecture:" && the processor
case "win32"
- return "windows"
+ if the processor is "x86" then
+ return "win-x86"
+ end if
+ if the processor is "x86_64" then
+ return "win-x86_64"
+ end if
+ throw "Unknown Windows architecture:" && the processor
case "macos"
return "macosx"
case "iphone"
@@ -153,8 +159,10 @@ command builderFetchEngine pVersion, pPlatform
end if
if sEngineDir is not empty then
switch pPlatform
- case "windows"
+ case "win-x86"
return sEngineDir & slash & "win-x86-bin"
+ case "win-x86_64"
+ return sEngineDir & slash & "win-x86_64-bin"
case "linux-x86"
return sEngineDir & slash & "linux-x86-bin"
case "linux-x86_64"
@@ -183,7 +191,8 @@ command builderFetchEngine pVersion, pPlatform
end if
local tPlatform
switch pPlatform
- case "windows"
+ case "win-x86"
+ case "win-x86_64"
get "windows/release"
break
case "linux-x86"
@@ -453,7 +462,8 @@ function builderInstallerEngine pPlatform
put the result into tEngineFolder
switch pPlatform
- case "windows"
+ case "win-x86"
+ case "win-x86_64"
return tEngineFolder & slash & "installer.exe"
case "linux-x86"
return tEngineFolder & slash & "installer"
diff --git a/builder/server_builder.livecodescript b/builder/server_builder.livecodescript
index 2bc37a1c0e1..5e33b17fe69 100644
--- a/builder/server_builder.livecodescript
+++ b/builder/server_builder.livecodescript
@@ -36,7 +36,7 @@ command serverBuilderRun pPlatform, pEdition
-- Clean up any existing output file
delete file tOutputFile
- if pPlatform is "windows" then
+ if pPlatform begins with "win-" then
repeat for each word tExternal in "revdb revzip revxml dbsqlite dbmysql dbpostgresql dbodbc"
get "server-" & tExternal & ".dll"
if there is not a file (tEngineFolder & slash & it) then
@@ -61,7 +61,7 @@ command serverBuilderRun pPlatform, pEdition
end if
local tExeExtension, tOutExeExtension
- if pPlatform is "windows" then
+ if pPlatform begins with "win-" then
put ".exe" into tExeExtension
put ".exe" into tOutExeExtension
--else if pPlatform is "linux" then
@@ -73,7 +73,7 @@ command serverBuilderRun pPlatform, pEdition
end if
local tLibExtension
- if pPlatform is "windows" then
+ if pPlatform begins with "win-" then
put ".dll" into tLibExtension
else if pPlatform is "macosx" then
put ".dylib" into tLibExtension
@@ -173,8 +173,10 @@ function getZipFilenameStub pVersion, pPlatform, pEdition
replace "." with "_" in pVersion
if pPlatform is "macosx" then
put "Mac" into pPlatform
- else if pPlatform is "windows" then
- put "Windows" into pPlatform
+ else if pPlatform is "win-x86" then
+ put "Windows-x86" into pPlatform
+ else if pPlatform is "win-x86_64" then
+ put "Windows-x86_64" into pPlatform
else if pPlatform is "linux-x86" then
put "Linux" into pPlatform
else if pPlatform is "linux-x86_64" then
diff --git a/builder/tools_builder.livecodescript b/builder/tools_builder.livecodescript
index 4a6bf468e7e..4732a6f866c 100644
--- a/builder/tools_builder.livecodescript
+++ b/builder/tools_builder.livecodescript
@@ -15,7 +15,7 @@ command toolsBuilderRun pPlatform, pEdition, pVersion
-- If on windows or linux, we can't do anything macosxy due to lack of lipo/strip :o(
local tEngineFolders
- get "windows linux-x86 linux-x86_64 linux-armv6hf macosx ios android-armeabi-v7a android-arm64-v8a android-x86 android-x86_64 emscripten"
+ get "win-x86 win-x86_64 linux-x86 linux-x86_64 linux-armv6hf macosx ios android-armeabi-v7a android-arm64-v8a android-x86 android-x86_64 emscripten"
repeat for each word tPlatform in it
builderFetchEngine pVersion, tPlatform
@@ -112,9 +112,6 @@ private command toolsBuilderFilterExternals pFolder, pPlatform
end repeat
end if
- -- remove windows 64 bit builds only required for filemaker
- get shell("rm -fv *x86_64.dll")
-
-- If the directory contains no code any more, remove it
put the files & return & the folders into tFiles
filter lines of tFiles with regex pattern "^.*\.(so|dylib|bundle|dll|lcext)$"
@@ -195,7 +192,8 @@ private command toolsBuilderMakePackage pVersion, pEdition, pPlatform, pEngineFo
packageCompilerConfigureSource tPackager, "linux-x86", pEngineFolders["linux-x86"]
packageCompilerConfigureSource tPackager, "linux-x86_64", pEngineFolders["linux-x86_64"]
packageCompilerConfigureSource tPackager, "linux-armv6-hf", pEngineFolders["linux-armv6hf"]
- packageCompilerConfigureSource tPackager, "windows", pEngineFolders["windows"]
+ packageCompilerConfigureSource tPackager, "win-x86", pEngineFolders["win-x86"]
+ packageCompilerConfigureSource tPackager, "win-x86_64", pEngineFolders["win-x86_64"]
packageCompilerConfigureSource tPackager, "ios", pEngineFolders["ios"]
packageCompilerConfigureSource tPackager, "android-armeabi-v7a", pEngineFolders["android-armeabi-v7a"]
packageCompilerConfigureSource tPackager, "android-arm64-v8a", pEngineFolders["android-arm64-v8a"]
@@ -223,6 +221,8 @@ private command toolsBuilderMakePackage pVersion, pEdition, pPlatform, pEngineFo
end if
if pPlatform begins with "linux" then
packageCompilerConfigureVariable tPackager, "TargetPlatform", "linux"
+ else if pPlatform begins with "win" then
+ packageCompilerConfigureVariable tPackager, "TargetPlatform", "windows"
else
packageCompilerConfigureVariable tPackager, "TargetPlatform", pPlatform
end if
@@ -231,11 +231,11 @@ private command toolsBuilderMakePackage pVersion, pEdition, pPlatform, pEngineFo
packageCompilerConfigureVariable tPackager, "EscapedVersionTag", tVersionEscaped
packageCompilerConfigureVariable tPackager, "ProductBranch", char 1 to 3 of pVersion
packageCompilerConfigureVariable tPackager, "TargetArchitectures", "i386"
- if pPlatform is "linux-x86" then
+ if pPlatform ends with "-x86" then
packageCompilerConfigureVariable tPackager, "TargetArchitecture", "x86"
- else if pPlatform is "linux-x86_64" then
+ else if pPlatform ends with "-x86_64" then
packageCompilerConfigureVariable tPackager, "TargetArchitecture", "x86_64"
- else if pPlatform is "linux-armv6hf" then
+ else if pPlatform ends with "-armv6hf" then
packageCompilerConfigureVariable tPackager, "TargetArchitecture", "armv6-hf"
end if
@@ -423,7 +423,8 @@ private command toolsBuilderMakeInstaller pVersion, pEdition, pPlatform, pIdeFol
put return & "insert script of stack" && quote & "InstallerUtilities" & quote && "into back" after tParams["startup_script"]
switch pPlatform
- case "windows"
+ case "win-x86"
+ case "win-x86_64"
-- Process the manifest appropriately
local tManifestFile
get windowsManifest()
@@ -434,7 +435,7 @@ private command toolsBuilderMakeInstaller pVersion, pEdition, pPlatform, pIdeFol
put tManifestFile into tParams["manifest"]
-- First we deploy the installer unsigned
- put abstractPinFile(builderInstallerEngine("windows")) into tParams["engine"]
+ put abstractPinFile(builderInstallerEngine(pPlatform)) into tParams["engine"]
put tInstallerStackfile into tParams["stackfile"]
put pPackageFile into tParams["payload"]
put tOutputFileStub & ".unsigned.exe" into tParams["output"]
@@ -938,8 +939,10 @@ function getInstallerFilenameStub pVersion, pPlatform, pEdition
replace "." with "_" in pVersion
if pPlatform is "macosx" then
put "Mac" into pPlatform
- else if pPlatform is "windows" then
- put "Windows" into pPlatform
+ else if pPlatform is "win-x86" then
+ put "Windows-x86" into pPlatform
+ else if pPlatform is "win-x86_64" then
+ put "Windows-x86_64" into pPlatform
else if pPlatform begins with "linux" then
put "Linux" into pPlatform
end if
@@ -956,8 +959,10 @@ function getDmgFilenameStub pVersion, pPlatform, pEdition
replace "." with "_" in pVersion
if pPlatform is "macosx" then
put "Mac" into pPlatform
- else if pPlatform is "windows" then
- put "Windows" into pPlatform
+ else if pPlatform is "win-x86" then
+ put "Windows-x86" into pPlatform
+ else if pPlatform is "win-x86_64" then
+ put "Windows-x86_64" into pPlatform
else if pPlatform is "linux" or pPlatform is "linux-x64" or pPlatform is "linux-armv6hf" then
put "Linux" into pPlatform
end if
diff --git a/builder/windows_manifest.xml b/builder/windows_manifest.xml
index 00484d48e0f..e4e9fdc809d 100644
--- a/builder/windows_manifest.xml
+++ b/builder/windows_manifest.xml
@@ -18,6 +18,6 @@
-
+
diff --git a/configure.bat b/configure.bat
index cab2d7d1932..01a589bab79 100644
--- a/configure.bat
+++ b/configure.bat
@@ -13,7 +13,7 @@ REM When calling configure.bat from the command line, BUILD_EDITION is not defin
IF NOT DEFINED BUILD_EDITION SET BUILD_EDITION="community"
REM Target architecture currently defaults to 32-bit x86
-IF NOT DEFINED TARGET_ARCH SET TARGET_ARCH=x86
+IF NOT DEFINED TARGET_ARCH SET TARGET_ARCH=x64
REM Make sure TARGET_ARCH is always x86 or x86_64
diff --git a/docs/notes/feature-win64-deployment.md b/docs/notes/feature-win64-deployment.md
new file mode 100644
index 00000000000..4f7cb282f2a
--- /dev/null
+++ b/docs/notes/feature-win64-deployment.md
@@ -0,0 +1,5 @@
+# Deploy 64-bit Windows standalones
+
+You can now deploy 64-bit standalones for Windows. The `Standalone Settings`
+dialog now has a `Windows x86` and a `Windows x86_64` checkbox allowing you to
+choose to build either or both 32-bit and 64-bit executables.
diff --git a/engine/src/deploy.h b/engine/src/deploy.h
index 1e4ce162e47..76db8486562 100644
--- a/engine/src/deploy.h
+++ b/engine/src/deploy.h
@@ -537,4 +537,9 @@ bool MCDeployWritePayload(const MCDeployParameters& p_params, bool p_to_network,
////////////////////////////////////////////////////////////////////////////////
+bool MCDeployWindowsPEHeaderOffset(MCDeployFileRef p_file, uint32_t &r_pe_offset);
+bool MCDeployWindowsArchitecture(MCDeployFileRef p_file, uint32_t p_pe_offset, MCDeployArchitecture &r_platform);
+
+////////////////////////////////////////////////////////////////////////////////
+
#endif
diff --git a/engine/src/deploy_sign.cpp b/engine/src/deploy_sign.cpp
index fb5a7103162..d495d1f77d0 100644
--- a/engine/src/deploy_sign.cpp
+++ b/engine/src/deploy_sign.cpp
@@ -627,51 +627,45 @@ static bool MCDeployBuildSpcIndirectDataContent(BIO *p_hash, SpcIndirectDataCont
return t_success;
}
+constexpr uint32_t kSecurityEntryOffset32 = 152;
+constexpr uint32_t kSecurityEntryOffset64 = 168;
+
// This method checks to see if the input file is a valid Windows EXE (well, as
// valid as we need it to be). It then returns the offset to the PE header if
// successful. Additionally, we return the offset of the certificate entry, or
// the length of the file (if no current cert).
-static bool MCDeploySignCheckWindowsExecutable(MCDeployFileRef p_input, uint32_t& r_pe_offset, uint32_t& r_cert_offset)
+static bool MCDeploySignCheckWindowsExecutable(MCDeployFileRef p_input, uint32_t& r_pe_offset, uint32_t& r_cert_offset, MCDeployArchitecture &r_architecture)
{
// First get the length of the input file
uint32_t t_length;
if (!MCDeployFileMeasure(p_input, t_length))
return false;
- // Now check the first two bytes - these should be MZ
- char t_buffer[4];
- if (!MCDeployFileReadAt(p_input, t_buffer, 2, 0) ||
- !MCMemoryEqual(t_buffer, "MZ", 2))
- return MCDeployThrow(kMCDeployErrorWindowsBadDOSSignature);
-
- // Now read in the offset to the pe header - this resides at
- // byte offset 60 (member e_lfanew in IMAGE_DOS_HEADER).
uint32_t t_offset;
- if (t_length < 64 ||
- !MCDeployFileReadAt(p_input, &t_offset, 4, 60))
- return MCDeployThrow(kMCDeployErrorWindowsBadDOSHeader);
-
- // Swap from non-network to host byte order
- MCDeployByteSwap32(false, t_offset);
-
- // Check the NT header is big enough - here 160 is the minimum size of the
- // NT header we need. This is:
- // 4 byte signature
- // 20 byte file header
- // 28 byte standard header
- // 68 byte optional header
- // 40 byte data directory (i.e. up to and including SECURITY entry).
- if (t_length < t_offset + 160)
- return MCDeployThrow(kMCDeployErrorWindowsNoNTHeader);
-
- // Now make sure the NT Signature is correct and read in the existing cert
- // fields. Note that the offset here is that of the 5th data directory entry
- // (4 + 20 + 28 + 64 + 5 * 8).
+ if (!MCDeployWindowsPEHeaderOffset(p_input, t_offset))
+ return false;
+
+ MCDeployArchitecture t_arch;
+ if (!MCDeployWindowsArchitecture(p_input, t_offset, t_arch))
+ return false;
+
+ uint32_t t_security_offset = t_offset;
+ if (t_arch == kMCDeployArchitecture_I386)
+ {
+ t_security_offset += kSecurityEntryOffset32;
+ }
+ else
+ {
+ t_security_offset += kSecurityEntryOffset64;
+ }
+
+ // Now read in the existing cert fields. Note that the offset here is
+ // that of the 5th data directory entry
uint32_t t_cert_section[2];
- if (!MCDeployFileReadAt(p_input, t_buffer, 4, t_offset) ||
- !MCMemoryEqual(t_buffer, "PE\0\0", 4) ||
- !MCDeployFileReadAt(p_input, t_cert_section, 2 * sizeof(uint32_t), t_offset + 152))
+ if (!MCDeployFileReadAt(p_input, t_cert_section, 2 * sizeof(uint32_t), t_security_offset))
+ {
return MCDeployThrow(kMCDeployErrorWindowsBadNTSignature);
+ }
MCDeployByteSwap32(false, t_cert_section[0]);
MCDeployByteSwap32(false, t_cert_section[1]);
@@ -687,6 +681,7 @@ static bool MCDeploySignCheckWindowsExecutable(MCDeployFileRef p_input, uint32_t
r_cert_offset = t_length;
r_pe_offset = t_offset;
+ r_architecture = t_arch;
return true;
}
@@ -720,7 +715,7 @@ static bool MCDeploySignCopyFileAt(BIO *p_output, MCDeployFileRef p_input, uint3
// This method reconstructs the output executable from the input executable
// while computing the hash of the critical parts of the file.
-static bool MCDeploySignHashWindowsExecutable(MCDeployFileRef p_input, BIO *p_output, uint32_t p_pe_offset, uint32_t p_cert_offset, BIO*& r_hash)
+static bool MCDeploySignHashWindowsExecutable(MCDeployFileRef p_input, BIO *p_output, uint32_t p_pe_offset, uint32_t p_cert_offset, MCDeployArchitecture p_architecture, BIO*& r_hash)
{
bool t_success;
t_success = true;
@@ -742,8 +737,9 @@ static bool MCDeploySignHashWindowsExecutable(MCDeployFileRef p_input, BIO *p_ou
// the input executable as we go.
// The first part of the output file is everything up to the start of the
- // 'CheckSum' field of the IMAGE_OPTIONAL_HEADER32 structure. This is at
- // offset 88 in said structure. This part is part of the hash.
+ // 'CheckSum' field of the IMAGE_OPTIONAL_HEADER structure. This is at
+ // offset 88 in both IMAGE_OPTIONAL_HEADER32 and IMAGE_OPTIONAL_HEADER64.
+ // This part is part of the hash.
if (t_success)
t_success = MCDeploySignCopyFileAt(t_hash, p_input, 0, p_pe_offset + 88);
@@ -757,20 +753,30 @@ static bool MCDeploySignHashWindowsExecutable(MCDeployFileRef p_input, BIO *p_ou
t_success = MCDeployThrowOpenSSL(kMCDeployErrorBadWrite);
}
+ uint32_t t_security_offset = p_pe_offset;
+ if (p_architecture == kMCDeployArchitecture_I386)
+ {
+ t_security_offset += kSecurityEntryOffset32;
+ }
+ else
+ {
+ t_security_offset += kSecurityEntryOffset64;
+ }
+
// Next is the section of the header after the CheckSum field and up to
- // the 'Security' data directory entry. This entry is at offset 152.
+ // the 'Security' data directory entry.
if (t_success)
- t_success = MCDeploySignCopyFileAt(t_hash, p_input, p_pe_offset + 92, 60);
+ t_success = MCDeploySignCopyFileAt(t_hash, p_input, p_pe_offset + 92, t_security_offset - (p_pe_offset + 92));
// Now write out the (current) value of the Security data directory entry,
// but not into the hash.
if (t_success)
- t_success = MCDeploySignCopyFileAt(p_output, p_input, p_pe_offset + 152, 8);
+ t_success = MCDeploySignCopyFileAt(p_output, p_input, t_security_offset, 8);
// After the Security data directory, everything up to the cert offset is
// hashed.
if (t_success)
- t_success = MCDeploySignCopyFileAt(t_hash, p_input, p_pe_offset + 160, p_cert_offset - (p_pe_offset + 160));
+ t_success = MCDeploySignCopyFileAt(t_hash, p_input, t_security_offset + 8, p_cert_offset - (t_security_offset + 8));
// Finally we round the output up to the nearest 8 bytes.
if (t_success && (p_cert_offset % 8 != 0))
@@ -1047,6 +1053,8 @@ static bool MCDeploySignWindowsAddTimeStamp(const MCDeploySignParameters& p_para
return t_success;
}
+static bool s_objects_created = false;
+
bool MCDeploySignWindows(const MCDeploySignParameters& p_params)
{
bool t_success;
@@ -1094,13 +1102,14 @@ bool MCDeploySignWindows(const MCDeploySignParameters& p_params)
// Next we check the input file, and compute the hash, writing out the new
// version of the executable as we go.
uint32_t t_pe_offset, t_cert_offset;
+ MCDeployArchitecture t_arch;
if (t_success)
- t_success = MCDeploySignCheckWindowsExecutable(t_input, t_pe_offset, t_cert_offset);
+ t_success = MCDeploySignCheckWindowsExecutable(t_input, t_pe_offset, t_cert_offset, t_arch);
BIO *t_hash;
t_hash = nil;
if (t_success)
- t_success = MCDeploySignHashWindowsExecutable(t_input, t_output, t_pe_offset, t_cert_offset, t_hash);
+ t_success = MCDeploySignHashWindowsExecutable(t_input, t_output, t_pe_offset, t_cert_offset, t_arch, t_hash);
// Next we create a PKCS#7 object ready for filling with the stuff we need for
// Authenticode.
@@ -1145,12 +1154,18 @@ bool MCDeploySignWindows(const MCDeploySignParameters& p_params)
// The various ASN.1 structures we are going to use require a number of ObjectIDs.
// We register them all here, to save having to check the return value of OBJ_txt2obj.
- if (t_success)
+ if (t_success && !s_objects_created)
+ {
if (!OBJ_create(SPC_INDIRECT_DATA_OBJID, SPC_INDIRECT_DATA_OBJID, SPC_INDIRECT_DATA_OBJID) ||
!OBJ_create(SPC_PE_IMAGE_DATA_OBJID, SPC_PE_IMAGE_DATA_OBJID, SPC_PE_IMAGE_DATA_OBJID) ||
!OBJ_create(SPC_STATEMENT_TYPE_OBJID, SPC_STATEMENT_TYPE_OBJID, SPC_STATEMENT_TYPE_OBJID) ||
!OBJ_create(SPC_SP_OPUS_INFO_OBJID, SPC_SP_OPUS_INFO_OBJID, SPC_SP_OPUS_INFO_OBJID))
+ {
t_success = MCDeployThrowOpenSSL(kMCDeployErrorBadSignature);
+ }
+
+ s_objects_created = true;
+ }
// Authenticode signatures require a single SignerInfo structure to be present.
// To create this we add a signature for the certificate we just located.
@@ -1305,6 +1320,16 @@ bool MCDeploySignWindows(const MCDeploySignParameters& p_params)
// ... And update the SECURITY table entry in the PE header appropraitely.
if (t_success)
{
+ uint32_t t_security_offset = t_pe_offset;
+ if (t_arch == kMCDeployArchitecture_I386)
+ {
+ t_security_offset += kSecurityEntryOffset32;
+ }
+ else
+ {
+ t_security_offset += kSecurityEntryOffset64;
+ }
+
uint32_t t_entry[2];
// First entry is the offset of the cert, making sure it is padded to 8
@@ -1315,7 +1340,7 @@ bool MCDeploySignWindows(const MCDeploySignParameters& p_params)
t_entry[1] = 8 + t_signature_size + (t_signature_size % 8 != 0 ? (8 - (t_signature_size % 8)) : 0);
MCDeployByteSwapRecord(false, "ll", t_entry, sizeof(t_entry));
- if (BIO_seek(t_output, t_pe_offset + 152) == -1 ||
+ if (BIO_seek(t_output, t_security_offset) == -1 ||
BIO_write(t_output, t_entry, sizeof(t_entry)) != sizeof(t_entry))
t_success = MCDeployThrowOpenSSL(kMCDeployErrorBadWrite);
}
diff --git a/engine/src/deploy_windows.cpp b/engine/src/deploy_windows.cpp
index 505846ddb14..36bcd6a4ba7 100644
--- a/engine/src/deploy_windows.cpp
+++ b/engine/src/deploy_windows.cpp
@@ -31,6 +31,12 @@ along with LiveCode. If not see . */
#include "deploy.h"
+constexpr uint32_t kAddressToPEAddress = 60;
+constexpr uint32_t kPEAddressSize = 4;
+constexpr uint32_t kMagicOffset = 0x18;
+constexpr uint16_t kHeaderMagic32 = 0x10b;
+constexpr uint16_t kHeaderMagic64 = 0x20b;
+
////////////////////////////////////////////////////////////////////////////////
//
// This section contains definitions for the various structures needed to
@@ -43,7 +49,8 @@ along with LiveCode. If not see . */
#define FIELD_OFFSET(type, field) ((LONG)(intptr_t)&(((type *)0)->field))
#endif
-#if !defined(_WIN32)
+// Defining common types for 32 and 64 bit
+#if !defined(_WIN32) && !defined(_WIN64)
typedef char CHAR;
typedef unsigned short WCHAR;
@@ -157,65 +164,6 @@ typedef struct _IMAGE_DATA_DIRECTORY {
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-//
-// Optional header format.
-//
-
-typedef struct _IMAGE_OPTIONAL_HEADER {
- //
- // Standard fields.
- //
-
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
-
- //
- // NT additional fields.
- //
-
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
-
-typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
-typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
-#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
-
-typedef struct _IMAGE_NT_HEADERS {
- DWORD Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER32 OptionalHeader;
-} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
-
-typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
-typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
// Directory Entries
@@ -442,9 +390,155 @@ typedef struct tagVS_FIXEDFILEINFO
DWORD dwFileDateMS; /* e.g. 0 */
DWORD dwFileDateLS; /* e.g. 0 */
} VS_FIXEDFILEINFO;
+#endif
+
+#if !defined(_WIN32)
+//
+// Optional header format.
+//
+typedef struct _IMAGE_OPTIONAL_HEADER_32 {
+ //
+ // Standard fields.
+ //
+
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+
+ //
+ // NT additional fields.
+ //
+
+ DWORD ImageBase; // l
+ DWORD SectionAlignment; // l
+ DWORD FileAlignment; // l
+ WORD MajorOperatingSystemVersion; // s
+ WORD MinorOperatingSystemVersion; // s
+ WORD MajorImageVersion; // s
+ WORD MinorImageVersion; // s
+ WORD MajorSubsystemVersion; // s
+ WORD MinorSubsystemVersion; // s
+ DWORD Win32VersionValue; // l
+ DWORD SizeOfImage; // l
+ DWORD SizeOfHeaders; // l
+ DWORD CheckSum; // l
+ WORD Subsystem; // s
+ WORD DllCharacteristics; // s
+ DWORD SizeOfStackReserve; // l
+ DWORD SizeOfStackCommit; // l
+ DWORD SizeOfHeapReserve; // l
+ DWORD SizeOfHeapCommit; // l
+ DWORD LoaderFlags; // l
+ DWORD NumberOfRvaAndSizes; // l
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
+
+// The following section should move to the template args
+// in the templated version of MCDeployWindows
+
+/*
+typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
+typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
+*/
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
+
+
+typedef struct _IMAGE_NT_HEADERS {
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
+
+// The following section should move to the template args
+// in the templated version of MCDeployWindows
+
+/*
+typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
+typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
+*/
#endif // if !defined(_WIN32)
+#if !defined(_WIN64) && !defined(_WINNT_)
+
+typedef uint64_t ULONGLONG;
+
+//
+// Optional header format.
+//
+
+typedef struct _IMAGE_OPTIONAL_HEADER_64 {
+ // Standard fields
+
+ WORD Magic; // s
+ BYTE MajorLinkerVersion; // b
+ BYTE MinorLinkerVersion; // b
+ DWORD SizeOfCode; // l
+ DWORD SizeOfInitializedData; // l
+ DWORD SizeOfUninitializedData; // l
+ DWORD AddressOfEntryPoint; // l
+ DWORD BaseOfCode; // l
+
+ // NT Fields
+
+ ULONGLONG ImageBase; // q
+ DWORD SectionAlignment; // l
+ DWORD FileAlignment; // l
+ WORD MajorOperatingSystemVersion; // s
+ WORD MinorOperatingSystemVersion; // s
+ WORD MajorImageVersion; // s
+ WORD MinorImageVersion; // s
+ WORD MajorSubsystemVersion; // s
+ WORD MinorSubsystemVersion; // s
+ DWORD Win32VersionValue; // l
+ DWORD SizeOfImage; // l
+ DWORD SizeOfHeaders; // l
+ DWORD CheckSum; // l
+ WORD Subsystem; // s
+ WORD DllCharacteristics; // s
+ ULONGLONG SizeOfStackReserve; // q
+ ULONGLONG SizeOfStackCommit; // q
+ ULONGLONG SizeOfHeapReserve; // q
+ ULONGLONG SizeOfHeapCommit; // q
+ DWORD LoaderFlags; // l
+ DWORD NumberOfRvaAndSizes; // l
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+
+ // sbbl lll l q ll ss ss ss l l l l s s q q q q l l
+} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
+
+// The following section should move to the template args
+// in the templated version of MCDeployWindows
+
+/*
+typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
+typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
+*/
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC
+
+
+typedef struct _IMAGE_NT_HEADERS_64 {
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
+
+// The following section should move to the template args
+// in the templated version of MCDeployWindows
+
+/*
+typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
+typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
+*/
+
+#endif // if !defined(_WIN64)
+
// The following structures are for those used in ICO files and in ICON and
// GROUP_ICON resources. These (for some reason) do not appear in any of the
// windows headers, so we replicate them for all platforms here.
@@ -570,10 +664,10 @@ static inline void swap_format(const char *f, void *p, uint32_t s)
// wrapping these in __BIG_ENDIAN__ switches, since (hopefully) even the poorest
// of optimizers will notice that the functions they are calling are no-ops :o)
-static inline void swap_IMAGE_NT_HEADERS(IMAGE_NT_HEADERS& x)
+template
+static inline void swap_IMAGE_NT_HEADERS(typename DeployPlatformTrait::IMAGE_NT_HEADERS& x)
{
- swap_format("l sslllss", &x, FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader));
- swap_format("sbbllllll lllssssssllllssllllll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll", &x . OptionalHeader, x . FileHeader . SizeOfOptionalHeader);
+ DeployPlatformTrait::swap_IMAGE_NT_HEADERS(x);
}
static inline void swap_IMAGE_DOS_HEADER(IMAGE_DOS_HEADER& x)
@@ -629,6 +723,36 @@ static inline void swap_GRPICONDIRENTRY(GRPICONDIRENTRY& x)
// This section contains methods for operating on a Windows PE resource tree.
//
+struct MCWindowsPE32Traits
+{
+ typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
+ typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
+
+ typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
+ typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
+
+ static inline void swap_IMAGE_NT_HEADERS(IMAGE_NT_HEADERS& x)
+ {
+ swap_format("l sslllss", &x, FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader));
+ swap_format("sbbllllll lllssssssllllssllllll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll", &x.OptionalHeader, x.FileHeader.SizeOfOptionalHeader);
+ }
+};
+
+struct MCWindowsPE64Traits
+{
+ typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
+ typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
+
+ typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
+ typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
+
+ static inline void swap_IMAGE_NT_HEADERS(IMAGE_NT_HEADERS& x)
+ {
+ swap_format("l sslllss", &x, FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader));
+ swap_format("sbblllll qllssssssllllssqqqqll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll ll", &x.OptionalHeader, x.FileHeader.SizeOfOptionalHeader);
+ }
+};
+
struct MCWindowsResources
{
// The id of the resource
@@ -1597,7 +1721,8 @@ static bool MCWindowsResourcesWrite(MCWindowsResources& self, uint32_t p_address
// PE, appropriately munge it and write out a new one.
//
-static bool MCDeployToWindowsReadHeaders(MCDeployFileRef p_file, IMAGE_DOS_HEADER& r_dos_header, IMAGE_NT_HEADERS& r_nt_header, IMAGE_SECTION_HEADER*& r_section_headers)
+template
+static bool MCDeployToWindowsReadHeaders(MCDeployFileRef p_file, IMAGE_DOS_HEADER& r_dos_header, typename DeployPlatformTrait::IMAGE_NT_HEADERS& r_nt_header, IMAGE_SECTION_HEADER*& r_section_headers)
{
if (!MCDeployFileRead(p_file, &r_dos_header, sizeof(IMAGE_DOS_HEADER)))
return MCDeployThrow(kMCDeployErrorWindowsNoDOSHeader);
@@ -1610,15 +1735,15 @@ static bool MCDeployToWindowsReadHeaders(MCDeployFileRef p_file, IMAGE_DOS_HEADE
if (!MCDeployFileSeekSet(p_file, r_dos_header . e_lfanew))
return MCDeployThrow(kMCDeployErrorWindowsBadDOSHeader);
- if (!MCDeployFileRead(p_file, &r_nt_header, sizeof(IMAGE_NT_HEADERS)))
+ if (!MCDeployFileRead(p_file, &r_nt_header, sizeof(typename DeployPlatformTrait::IMAGE_NT_HEADERS)))
return MCDeployThrow(kMCDeployErrorWindowsNoNTHeader);
- swap_IMAGE_NT_HEADERS(r_nt_header);
+ DeployPlatformTrait::swap_IMAGE_NT_HEADERS(r_nt_header);
if (r_nt_header . Signature != IMAGE_NT_SIGNATURE)
return MCDeployThrow(kMCDeployErrorWindowsBadNTSignature);
- if (!MCDeployFileSeekSet(p_file, r_dos_header . e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + r_nt_header . FileHeader . SizeOfOptionalHeader))
+ if (!MCDeployFileSeekSet(p_file, r_dos_header . e_lfanew + FIELD_OFFSET(typename DeployPlatformTrait::IMAGE_NT_HEADERS, OptionalHeader) + r_nt_header . FileHeader . SizeOfOptionalHeader))
return MCDeployThrow(kMCDeployErrorWindowsBadSectionHeaderOffset);
r_section_headers = new (nothrow) IMAGE_SECTION_HEADER[r_nt_header . FileHeader . NumberOfSections];
@@ -1653,8 +1778,11 @@ static bool MCDeployToWindowsReadHeaders(MCDeployFileRef p_file, IMAGE_DOS_HEADE
// section, and that (as is usual) the '.rsrc' section is at the end of the
// executable.
//
+template
Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
{
+ typedef typename DeployPlatformTrait::IMAGE_NT_HEADERS IMAGE_NT_HEADERS;
+
bool t_success;
t_success = true;
@@ -1677,8 +1805,8 @@ Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
IMAGE_SECTION_HEADER *t_section_headers;
t_section_headers = NULL;
if (t_success)
- t_success = MCDeployToWindowsReadHeaders(t_engine, t_dos_header, t_nt_header, t_section_headers);
-
+ t_success = MCDeployToWindowsReadHeaders(t_engine, t_dos_header, t_nt_header, t_section_headers);
+
IMAGE_SECTION_HEADER *t_payload_section, *t_project_section, *t_resource_section;
t_payload_section = t_project_section = t_resource_section = nil;
@@ -1841,7 +1969,7 @@ Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
if (t_success)
{
t_optional_header_size = MCU_min(sizeof(t_nt_header . OptionalHeader), (uint4)t_nt_header . FileHeader . SizeOfOptionalHeader);
- t_optional_header_offset = t_dos_header . e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader);
+ t_optional_header_offset = t_dos_header . e_lfanew + FIELD_OFFSET(typename DeployPlatformTrait::IMAGE_NT_HEADERS, OptionalHeader);
t_section_headers_offset = t_optional_header_offset + t_nt_header . FileHeader . SizeOfOptionalHeader;
uint32_t t_payload_section_size, t_payload_section_delta;
@@ -1908,7 +2036,7 @@ Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
t_nt_header . OptionalHeader . DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] . Size = t_resource_section_size;
// Byte swap everything we are about to write out
- swap_IMAGE_NT_HEADERS(t_nt_header);
+ DeployPlatformTrait::swap_IMAGE_NT_HEADERS(t_nt_header);
for(uint32_t i = 0; i < t_section_count; i++)
swap_IMAGE_SECTION_HEADER(t_section_headers[i]);
}
@@ -1935,3 +2063,119 @@ Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
return t_success ? ES_NORMAL : ES_ERROR;
}
+
+bool MCDeployWindowsPEHeaderOffset(MCDeployFileRef p_file, uint32_t &r_pe_offset)
+{
+ // Now check the first two bytes - these should be MZ
+ char t_buffer[4];
+ if (!MCDeployFileReadAt(p_file, t_buffer, 2, 0) ||
+ !MCMemoryEqual(t_buffer, "MZ", 2))
+ {
+ return MCDeployThrow(kMCDeployErrorWindowsBadDOSSignature);
+ }
+
+ // Now read in the offset to the pe header - this resides at
+ // byte offset 60 (member e_lfanew in IMAGE_DOS_HEADER).
+ uint32_t t_offset;
+ if (!MCDeployFileReadAt(p_file, &t_offset, kPEAddressSize, kAddressToPEAddress))
+ {
+ return MCDeployThrow(kMCDeployErrorWindowsBadDOSHeader);
+ }
+
+ // Swap from non-network to host byte order
+ MCDeployByteSwap32(false, t_offset);
+ r_pe_offset = t_offset;
+
+ return true;
+}
+
+// Do some basic validation on the NT header and return the file architecture
+bool MCDeployWindowsArchitecture(MCDeployFileRef p_file, uint32_t p_pe_offset, MCDeployArchitecture &r_platform)
+{
+ bool t_success;
+ t_success = true;
+
+ uint32_t t_length;
+ if (!MCDeployFileMeasure(p_file, t_length))
+ return false;
+
+ // Confirm NT Signature at offset
+ char t_buffer[4];
+ if (t_success && (!MCDeployFileReadAt(p_file, t_buffer, 4, p_pe_offset) ||
+ !MCMemoryEqual(t_buffer, "PE\0\0", 4)))
+ {
+ t_success = MCDeployThrow(kMCDeployErrorWindowsNoNTHeader);
+ }
+
+ uint16_t t_magic;
+ if (t_success && !MCDeployFileReadAt(p_file, &t_magic, sizeof(uint16_t), p_pe_offset + kMagicOffset))
+ {
+ t_success = MCDeployThrow(kMCDeployErrorWindowsNoNTHeader);
+ }
+
+ if (t_success)
+ {
+ swap_uint16(t_magic);
+
+ switch (t_magic)
+ {
+ case kHeaderMagic32:
+ r_platform = kMCDeployArchitecture_I386;
+ break;
+ case kHeaderMagic64:
+ r_platform = kMCDeployArchitecture_X86_64;
+ break;
+ default:
+ t_success = MCDeployThrow(kMCDeployErrorWindowsNoNTHeader);
+ break;
+ }
+ }
+
+ return t_success;
+}
+
+Exec_stat MCDeployToWindows(const MCDeployParameters& p_params)
+{
+ bool t_success = true;
+
+ MCDeployFileRef t_engine;
+ t_engine = nullptr;
+ if (t_success && !MCDeployFileOpen(p_params.engine, kMCOpenFileModeRead, t_engine))
+ {
+ t_success = MCDeployThrow(kMCDeployErrorNoEngine);
+ }
+
+ uint32_t t_pe_offset;
+ if (t_success)
+ {
+ t_success = MCDeployWindowsPEHeaderOffset(t_engine, t_pe_offset);
+ }
+
+ MCDeployArchitecture t_arch;
+ if (t_success)
+ {
+ t_success = MCDeployWindowsArchitecture(t_engine, t_pe_offset, t_arch);
+ }
+
+ if (t_engine != nullptr)
+ {
+ MCDeployFileClose(t_engine);
+ }
+
+ if (t_success)
+ {
+ switch (t_arch)
+ {
+ case kMCDeployArchitecture_I386: {
+ return MCDeployToWindows(p_params);
+ }
+ case kMCDeployArchitecture_X86_64: {
+ return MCDeployToWindows(p_params);
+ }
+ default:
+ MCUnreachableReturn(ES_ERROR)
+ }
+ }
+
+ return ES_ERROR;
+}
diff --git a/ide-support/revsaveasstandalone.livecodescript b/ide-support/revsaveasstandalone.livecodescript
index 5c98c9f3b30..365d3a7635a 100644
--- a/ide-support/revsaveasstandalone.livecodescript
+++ b/ide-support/revsaveasstandalone.livecodescript
@@ -436,10 +436,15 @@ private function revStandalonePlatformDetails pTarget
put "x86-32" into tDetailsA["architecture"]
break
case "Windows"
- put "Windows/x86-32" into tArchFolder
+ if pTarget is "Windows" then
+ put "Windows/x86-32" into tArchFolder
+ put "x86-32" into tDetailsA["architecture"]
+ else if pTarget is "Windows x86-64" then
+ put "Windows/x86-64" into tArchFolder
+ put "x86-64" into tDetailsA["architecture"]
+ end if
put ".dll" into tDetailsA["loadable_extension"]
put "Windows" into tDetailsA["platform"]
- put "x86-32" into tDetailsA["architecture"]
break
case "Linux"
if pTarget is "Linux" then
@@ -774,13 +779,16 @@ command revSaveAsWindowsStandalone pStack, pRestoreFileName, pFolder, @xStandalo
-- Ensure standalone settings script local is reset when building for subsequent targets
put tStandaloneSettingsA into sStandaloneSettingsA
- local tArch
+ local tArch, tRuntimeDir
if word 2 of tTarget is among the items of "x64,x86-64,x86_64" then
put "x86_64" into tArch
+ put "x86-64" into tRuntimeDir
else if word 2 of tTarget is not empty then
put word 2 of tTarget into tArch
+ put word 2 of tTarget into tRuntimeDir
else
put "x86" into tArch
+ put "x86-32" into tRuntimeDir
end if
revStandalonePreBuild pStack, pFolder, "windows", tArch, tStackName, tStackFileList
if the result is not empty then
@@ -849,7 +857,7 @@ command revSaveAsWindowsStandalone pStack, pRestoreFileName, pFolder, @xStandalo
put empty into tManifestData
put false into tManifestNeeded
- put revEnvironmentRuntimePath() & "/Windows/x86-32/w32-manifest-template.xml" into tManifestPath
+ put revEnvironmentRuntimePath() & "/Windows/" & tRuntimeDir & "/w32-manifest-template.xml" into tManifestPath
if there is not a file tManifestPath then
revStandaloneAddWarning "Windows, manifest template not found: " & quote & tManifestPath & quote
else
@@ -863,7 +871,7 @@ command revSaveAsWindowsStandalone pStack, pRestoreFileName, pFolder, @xStandalo
if sStandaloneSettingsA["Windows,uacExecutionLevel"] is not empty and sStandaloneSettingsA["Windows,uacExecutionLevel"] is not "default" then
local tManifestTrustInfoPath
- put revEnvironmentRuntimePath() & "/Windows/x86-32/w32-manifest-template-trustinfo.xml" into tManifestTrustInfoPath
+ put revEnvironmentRuntimePath() & "/Windows/" & tRuntimeDir & "/w32-manifest-template-trustinfo.xml" into tManifestTrustInfoPath
if there is not a file tManifestTrustInfoPath then
revStandaloneAddWarning "Windows, manifest trustinfo template not found: " & quote & tManifestTrustInfoPath & quote
@@ -879,7 +887,7 @@ command revSaveAsWindowsStandalone pStack, pRestoreFileName, pFolder, @xStandalo
// IM-2014-08-15: [[ Bug 13118 ]] Pull in dpiAware section if set.
if sStandaloneSettingsA["Windows,usePixelScaling"] is empty or sStandaloneSettingsA["Windows,usePixelScaling"] is true then
local tManifestApplicationPath
- put revEnvironmentRuntimePath() & "/Windows/x86-32/w32-manifest-template-dpiaware.xml" into tManifestApplicationPath
+ put revEnvironmentRuntimePath() & "/Windows/" & tRuntimeDir & "/w32-manifest-template-dpiaware.xml" into tManifestApplicationPath
if there is not a file tManifestApplicationPath then
revStandaloneAddWarning "Windows, manifest dpiaware template not found: " & quote & tManifestApplicationPath & quote
@@ -2202,7 +2210,7 @@ private command revCopyCEFResources pPlatform, pStandalonePath, pCopyRevBrowserR
set the itemdel to slash
put item 1 to -2 of pStandalonePath into tCurrentLocation
switch
- case pPlatform = "Windows"
+ case pPlatform begins with "Windows"
put (item 1 to -2 of tExternalPath) & "/CEF" into tCEFResources
put tCurrentLocation & slash & "Externals/CEF" into tCEFDest
diff --git a/ide-support/revsblibrary.livecodescript b/ide-support/revsblibrary.livecodescript
index 0ba97c25714..4931befa250 100644
--- a/ide-support/revsblibrary.livecodescript
+++ b/ide-support/revsblibrary.livecodescript
@@ -709,7 +709,7 @@ function revFolderNameMakeLegal pName
end revFolderNameMakeLegal
// List of all desktop target platforms + architecture
-constant kDesktopTargets = "Windows,MacOSX x86-32,MacOSX x86-64,Linux,Linux x64,Linux armv6-hf"
+constant kDesktopTargets = "Windows,Windows x86-64,MacOSX x86-32,MacOSX x86-64,Linux,Linux x64,Linux armv6-hf"
function revSBDesktopTargets
return kDesktopTargets
end revSBDesktopTargets
@@ -724,13 +724,15 @@ function revSBTargetToPlatform pTarget
return "MacOSX"
else if pTarget begins with "Linux" then
return "Linux"
+ else if pTarget begins with "Windows" then
+ return "Windows"
else
return pTarget
end if
end revSBTargetToPlatform
-- item 1 of the architectures should be the default architecture
-constant kWindowsArchitectures = "x86-32"
+constant kWindowsArchitectures = "x86-32,x86-64"
constant kMacOSXArchitectures = "x86-32,x86-64"
constant kLinuxArchitectures = "x86-32,x86-64,armv6-hf"
constant kAndroidArchitectures = "armv7,arm64,x86,x86_64"
@@ -1020,6 +1022,11 @@ function revEngineCheck pEngine
return true
end if
break
+ case "Windows x86-64"
+ if there is a file (tPath & "/Windows/x86-64/Standalone") then
+ return true
+ end if
+ break
# OK-2007-08-07 : Added linux support
case "Linux"
if there is a file (tPath & "/Linux/x86-32/Standalone") then
@@ -3006,6 +3013,9 @@ function revSBEnginePath pPlatform
case "Windows"
return tRuntimePath & "/Windows/x86-32/Standalone"
break
+ case "Windows x86-64"
+ return tRuntimePath & "/Windows/x86-64/Standalone"
+ break
case "Linux"
return tRuntimePath & "/Linux/x86-32/Standalone"
break
diff --git a/lcidlc/lcidlc.gyp b/lcidlc/lcidlc.gyp
index 986e45e3268..af4cc659f59 100644
--- a/lcidlc/lcidlc.gyp
+++ b/lcidlc/lcidlc.gyp
@@ -76,12 +76,6 @@
'target_name': 'encode_support',
'type': 'none',
- 'sources':
- [
- 'src/Support.java',
- 'src/Support.mm',
- ],
-
'actions':
[
{