Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QoL Changes #1

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
# sxsc
A fork of [`echnobas`/sxsc](https://github.com/echnobas/sxsc) (the SxS compiler - pronounced sxs-see) for use in automatic package building for [Atlas](https://github.com/Atlas-OS/Atlas/actions/workflows/package-build.yaml).
A fork of [`echnobas`/sxsc](https://github.com/echnobas/sxsc) (the SxS compiler - pronounced sxs-see) for use in automatic package building for [Atlas](https://github.com/Atlas-OS/Atlas).

GNU General Public License v3.0 [license](https://github.com/echnobas/sxsc/blob/a45c5f321153a0dd33266cb35fce3effac7212ad/LICENSE).

### Changes
### General Changes
- Removed [`gullible_installer.ps1`](https://github.com/echnobas/sxsc/blob/master/gullible_installer.ps1)
- Not needed for building
- [`online-sxs.cmd`](https://github.com/he3als/online-sxs) is used instead
- Removed binaries
- They are included [by default](https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md#installed-windows-sdks) in the `windows-latest` GitHub Action runner
- Changed in the Python script to match that
- Removed binaries: `makecab, makecat, signtool`
- Removed binaries: `makecab, makecat, signtool`, use Windows Kit
- Add `requirements.txt`
- Files support
- Files support
- Enhanced `sxsc.py` for better usability by adding a search for any configuration files that start with `cfg` and end with `.yaml`. If multiple files are found, a file explorer prompts the user to select one.
- In `build.ps1` implemented a smart system to locate Windows Kit subfolders containing Windows build names, along with various qol improvements.

And other little changes...

>[!Important]
> To use the `sxsc` method, you need to have the Windows Kit, a configuration file (such as the [AtlasOS Configuration File](https://github.com/Atlas-OS/Atlas/tree/main/src/sxsc)), and a bit of expertise.
72 changes: 54 additions & 18 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,67 @@ param (
[string]$CabName
)

Write-Output "Setting the variables..."
$bin = Test-Path "bin"
$winKit = Get-ChildItem -Path "$([Environment]::GetFolderPath('ProgramFilesx86'))\Windows Kits\10\bin" -Directory -Filter '*.0*' |
Sort-Object -Descending |
Select-Object -First 1
if (($winKit.Count -eq 0) -and !$bin) { throw "Windows Kit not found!" }
$env:PATH += ";$winKit\x64"
if ($bin) { $env:path += ";$PWD\bin" }
Write-Host "Thumbprint: $Thumbprint" -ForegroundColor Green
Write-Host "CAB Name: $CabName" -ForegroundColor Green

# Check if required tools exist
$latestBinPath = (Get-ChildItem -Path "$([Environment]::GetFolderPath('ProgramFilesX86'))\Windows Kits\10\bin" -Directory | Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | Sort-Object { [Version]$_.Name } -Descending | Select-Object -First 1).FullName
$makecatPath = "$latestBinPath\x64\makecat.exe"
$signToolPath = "$latestBinPath\x64\signtool.exe"

if (-Not (Test-Path $makecatPath)) {
Write-Host "Makecat tool not found at: $makecatPath" -ForegroundColor Red
}
if (-Not (Test-Path $signToolPath)) {
Write-Host "SignTool not found at: $signToolPath" -ForegroundColor Red
}

# Ensure tools are present before continuing
if (-Not (Test-Path $makecatPath) -or -Not (Test-Path $signToolPath)) {
Write-Host "Required tools not found in the specified paths. Aborting." -ForegroundColor Red
exit 1
}

Write-Output "Making CAT..."
$cat = makecat update.cdf
if ($LASTEXITCODE -ne 0) { throw "Failed to make CAT! $cat" }
$cat = & $makecatPath update.cdf 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to make CAT! Error: $cat" -ForegroundColor Red
} else {
Write-Host "Successfully created CAT." -ForegroundColor Green
}

Write-Output "Signing CAT..."
$cat1 = signtool sign /sm /uw /sha1 $Thumbprint /fd SHA256 update.cat
if ($LASTEXITCODE -ne 0) { throw "Failed to sign CAT! $cat1" }
$cat1 = & $signToolPath sign /debug /sm /uw /sha1 $Thumbprint /fd SHA256 update.cat 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to sign CAT! Error: $cat1" -ForegroundColor Red
} else {
Write-Host "Successfully signed CAT." -ForegroundColor Green
}

Write-Output "Making CAB..."
$cab = makecab /d "CabinetName1=$cabName" /f files.txt
if ($LASTEXITCODE -ne 0) { throw "Failed to make CAB! $cab" }
Remove-Item -Path "setup.*" -Force -EA 0
$cab = & makecab.exe /d "CabinetName1=$CabName" /f files.txt 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to make CAB! Error: $cab" -ForegroundColor Red
} else {
Write-Host "Successfully created CAB." -ForegroundColor Green
}
Remove-Item -Path "setup.*" -Force -ErrorAction SilentlyContinue

Write-Output "Signing CAB..."
$cab1 = signtool sign /sm /uw /sha1 $Thumbprint /fd SHA256 "disk1\$cabName"
if ($LASTEXITCODE -ne 0) { throw "Failed to sign CAB! $cab1" }
$cab1 = & $signToolPath sign /debug /sm /uw /sha1 $Thumbprint /fd SHA256 "disk1\$CabName" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to sign CAB! Error: $cab1" -ForegroundColor Red
} else {
Write-Host "Successfully signed CAB." -ForegroundColor Green
}

Write-Output "Copying CAB to main directory..."
Copy-Item -Path "disk1\*.cab" -Destination "." -Force
try {
Copy-Item -Path "disk1\*.cab" -Destination "$env:USERPROFILE\Desktop" -Force
Write-Host "CAB copied to desktop." -ForegroundColor Green
} catch {
Write-Host "Failed to copy CAB: $_" -ForegroundColor Red
}

Write-Host "Processing complete. Press Enter to exit..."
pause
3 changes: 2 additions & 1 deletion clean.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ if ($Thumbprint) {
".\disk1\*",
".\disk1",
"*.cab"
) | ForEach-Object { Remove-Item -Path $_ -Recurse -Force -EA 0 }
"__pycache__"
) | ForEach-Object { Remove-Item -Path $_ -Recurse -Force -EA 0 }
22 changes: 18 additions & 4 deletions make-cert.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Ensure administrator privileges
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) {
Write-Host "Restarting script with administrator privileges..." -ForegroundColor Yellow
Start-Process PowerShell.exe -ArgumentList ("-NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f $PSCommandPath) -Verb RunAs
exit
}

$store = 'Cert:\LocalMachine\My'
$params = @{
Type = 'Custom'
Expand All @@ -16,8 +23,15 @@ $params = @{
NotAfter = (Get-Date).AddMonths(9999)
CertStoreLocation = $store
}
(New-SelfSignedCertificate @params).Thumbprint

# $path = "$store\$((New-SelfSignedCertificate @params).Thumbprint)"
# Export-PfxCertificate -Cert $path -FilePath "sxs.pfx" -Password '1' -NoProperties
# Get-ChildItem $path | Remove-Item -Force
# Create the certificate and store its thumbprint
$thumbprint = (New-SelfSignedCertificate @params).Thumbprint

# Check if certificate exists
if (Get-ChildItem -Path $store | Where-Object { $_.Thumbprint -eq $thumbprint }) {
Write-Host "Certificate created with Thumbprint: $thumbprint" -ForegroundColor Green
} else {
Write-Host "Failed to create certificate" -ForegroundColor Red
}

pause
119 changes: 81 additions & 38 deletions sxsc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import yaml, havesxs, uuid, hashlib, base64, os, tempfile
import os
import yaml
import havesxs
import uuid
import hashlib
import base64
import tempfile
import tkinter as tk
from tkinter import filedialog
import subprocess

# FXEFqZQLNdyPGADgoUdluRUTzVkGUI/H7FOiuNUDjuk=
PUBLIC_KEY_TOKEN = "31bf3856ad364e35"
Expand Down Expand Up @@ -29,16 +38,14 @@ def __init__(
self.standalone = standalone

def generate_component_sxs(self):
return havesxs.generate_sxs_name(
{
"name": self.target_component,
"culture": "none",
"version": self.version,
"publicKeyToken": self.public_key_token,
"processorArchitecture": self.target_arch,
"versionScope": self.version_scope,
}
)
return havesxs.generate_sxs_name({
"name": self.target_component,
"culture": "none",
"version": self.version,
"publicKeyToken": self.public_key_token,
"processorArchitecture": self.target_arch,
"versionScope": self.version_scope,
})

def generate_component_manifest(self):
global tempDir
Expand Down Expand Up @@ -89,19 +96,17 @@ def generate_component_manifest(self):
files_list
]

def generate_update_sxs(self, culture = "none"):
return havesxs.generate_sxs_name(
{
"name": self.identifier,
"culture": culture,
"version": self.version,
"publicKeyToken": self.public_key_token,
"processorArchitecture": self.target_arch,
"versionScope": self.version_scope,
}
)

def generate_update_manifest(self, discoverable = False):
def generate_update_sxs(self, culture="none"):
return havesxs.generate_sxs_name({
"name": self.identifier,
"culture": culture,
"version": self.version,
"publicKeyToken": self.public_key_token,
"processorArchitecture": self.target_arch,
"versionScope": self.version_scope,
})

def generate_update_manifest(self, discoverable=False):
return f"""<?xml version="1.0" encoding="utf-8" standalone="{self.standalone}"?><assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0" copyright="{self.copyright}"><assemblyIdentity name="{self.identifier}" version="{self.version}" processorArchitecture="{self.target_arch}" language="neutral" buildType="release" publicKeyToken="{self.public_key_token}" versionScope="{self.version_scope}"/><deployment xmlns="urn:schemas-microsoft-com:asm.v3"/><dependency discoverable=\"{"true" if discoverable else "false"}\"><dependentAssembly dependencyType="install"><assemblyIdentity name="{self.target_component}" version="{self.version}" processorArchitecture="{self.target_arch}" language="neutral" buildType="release" publicKeyToken="{self.public_key_token}" versionScope="{self.version_scope}"/></dependentAssembly></dependency></assembly>"""


Expand All @@ -124,9 +129,38 @@ def generate_mum(self):
def generate_mum_update(self, update):
return f"""<update name="{update.identifier}"><component><assemblyIdentity name="{update.identifier}" version="{update.version}" processorArchitecture="{update.target_arch}" language="neutral" buildType="release" publicKeyToken="{update.public_key_token}" versionScope="{update.version_scope}"/></component></update>"""


with open("cfg.yaml", "r") as f:
config = yaml.safe_load(f)
def find_config_file():
script_dir = os.path.dirname(os.path.abspath(__file__))
cfg_files = [f for f in os.listdir(script_dir) if f.startswith("cfg") and f.endswith(".yaml")]
return cfg_files

def select_config_file():
root = tk.Tk()
root.withdraw() # Hide the main window
file_path = filedialog.askopenfilename(title="Select Configuration File", filetypes=[("YAML files", "*.yaml")])
return file_path

config_files = find_config_file()

if len(config_files) > 1:
print("Multiple configuration files found. Please select one.")
config_path = select_config_file()
elif len(config_files) == 1:
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), config_files[0])
else:
print("No configuration file found in the script's directory. Please select the path to your YAML configuration file.")
config_path = select_config_file()

if config_path:
try:
with open(config_path, "r") as f:
config = yaml.safe_load(f)
except FileNotFoundError:
print("Error: Configuration file not found. Please ensure the file path is correct.")
exit(1)
except yaml.YAMLError as e:
print(f"Error: Problem loading YAML file: {e}")
exit(1)

# Staging Arena
staged_updates = []
Expand Down Expand Up @@ -183,17 +217,26 @@ def generate_mum_update(self, update):
for (i, filename) in enumerate(filter(lambda f: f != "update.cat", staged_files)):
f.write(f"<HASH>F{i+1}={filename}\n")

with open(".\\start-build.ps1", "w+") as f:
f.write(f"""param (
[Parameter( Mandatory = $True )]
[string]$Thumbprint
# Generate Thumbprint
print("To create a thumbprint, please run 'make-cert.ps1' as an administrator in PowerShell.")

thumbprint = input("Enter the thumbprint generated: ")

# Create PowerShell script code directly in Python
build_script = f"""param (
[Parameter(Mandatory = $True)]
[string]$Thumbprint,
[string]$CabName
)

.\\build.ps1 -Thumbprint $Thumbprint -CabName '{config['package']}{PUBLIC_KEY_TOKEN}{config['target_arch']}{config['version']}.cab'""")
# Call build script with thumbprint
Start-Process powershell -ArgumentList '-ExecutionPolicy Bypass -File .\\build.ps1 -Thumbprint {thumbprint} -CabName "{config['package']}{PUBLIC_KEY_TOKEN}{config['target_arch']}{config['version']}.cab"'
"""

with open("build-script.ps1", "w+") as f:
f.write(build_script)

# Run PowerShell script in a separate window
subprocess.run(["powershell.exe", "-ExecutionPolicy", "Bypass", "-File", "build-script.ps1", "-Thumbprint", thumbprint], creationflags=subprocess.CREATE_NEW_CONSOLE)

if not tempDir == None:
with open(".\\start-build.ps1", 'a') as f:
f.write(f"""\n
Write-Output "Deleting temp folder..."
Remove-Item -Path '{tempDir}' -Force -Recurse
""")
print("Processing complete. You may close this window.")