diff --git a/.gitattributes b/.gitattributes
index 273764a214..7c59266ea4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,8 @@
+*.py text eol=lf
*.sh text eol=lf
*.exe binary
*.apk binary
*.so binary
*.xml text eol=crlf
+*.bat text eol=crlf
+*.ps1 text eol=crlf
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000..fad1cf6576
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,91 @@
+name: Bug report/反馈 Bug
+description: Report errors or unexpected behavior./反馈错误或异常行为。
+labels: [bug]
+title: "[Bug] Short description."
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for reporting issues of MagiskOnWSALocal!
+
+ To make it easier for us to help you please enter detailed information below.
+
+ 感谢给 MagiskOnWSALocal 汇报问题!
+ 为了使我们更好地帮助你,请提供以下信息。
+ 为了防止重复汇报,标题请务必使用英文。
+ - type: textarea
+ attributes:
+ label: Steps to reproduce/复现步骤
+ value: |
+ 1.
+ 2.
+ 3.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected behaviour/预期行为
+ placeholder: Tell us what should happen/正常情况下应该发生什么
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Actual behaviour/实际行为
+ placeholder: Tell us what happens instead/实际上发生了什么
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: MagiskOnWSALocal commit full SHA/MagiskOnWSALocal 提交的完整哈希
+ description: Don't use 'latest'. Copy and paste full commit SHA, otherwise your issue will be closed./不要填用“最新”。复制并粘贴完整 commit SHA,不然 issue 会被关闭。
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Linux distribution info/Linux 发行版信息
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Windows version/Windows 版本
+ placeholder: 10.0.22000.978
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Build Parameters/构建参数
+ description: The script prints the build information each time you start a build. It looks like this, please copy and paste it./每次开始构建时脚本都会打印构建信息,它看起来是这样的,请复制并粘贴上来。
+ placeholder: |
+ COMMAND_LINE=--arch x64 --release-type retail --magisk-ver stable --gapps-brand MindTheGapps --gapps-variant pico --root-sol magisk
+ INFO: Architecture: x64
+ INFO: Release Type: retail
+ INFO: Magisk Version: stable
+ INFO: GApps Brand: MindTheGapps
+ INFO: GApps Variant: pico
+ INFO: Root Solution: magisk
+ Build: RELEASE_TYPE=Retail
+ validations:
+ required: true
+ - type: checkboxes
+ id: latest
+ attributes:
+ label: Version requirement/版本要求
+ options:
+ - label: I am using latest commit of MagiskOnWSALocal/我正在使用最新 commit 的版本
+ required: true
+ - type: textarea
+ attributes:
+ label: Logs/日志
+ description: Please copy and paste the error or submit a screenshot. Without log, the issue will be closed. /请复制粘贴错误或提交截图。无日志提交会被关闭。
+ value: |
+
+
+ [//]: <> (Don't modify above)
+
+ ```
+ # Replace this line with the log / 将此行用日志替换
+ ```
+ [//]: <> (Don't modify below)
+
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..3e0476632d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Ask a question/提问
+ url: https://github.com/LSPosed/MagiskOnWSALocal/discussions/new?category=Q-A
+ about: Please ask and answer questions here./如果有任何疑问请在这里提问
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000000..9f826830d0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,24 @@
+---
+name: Feature request/新特性请求
+description: Suggest an idea./提出建议
+labels: [enhancement]
+title: "[Feature Request] Short description."
+body:
+ - type: textarea
+ attributes:
+ label: Is your feature request related to a problem?/你的请求是否与某个问题相关?
+ placeholder: A clear and concise description of what the problem is./请清晰准确表述该问题。
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the solution you'd like/描述你想要的解决方案
+ placeholder: A clear and concise description of what you want to happen./请清晰准确描述新特性的预期行为
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Additional context/其他信息
+ placeholder: Add any other context or screenshots about the feature request here./其他关于新特性的信息或者截图
+ validations:
+ required: false
\ No newline at end of file
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..6eda463153
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,11 @@
+
+
+Checklist
+
+- [ ] Referenced all related issues in the PR body (e.g. "Closes #xyz")
+- [ ] Have tested the modifications
diff --git a/.github/workflows/issue_moderator.yml b/.github/workflows/issue_moderator.yml
new file mode 100644
index 0000000000..6af31e2a84
--- /dev/null
+++ b/.github/workflows/issue_moderator.yml
@@ -0,0 +1,27 @@
+name: Issue moderator
+
+on:
+ issues:
+ types: [opened]
+ pull_request:
+ types: [opened, edited]
+
+jobs:
+ autoclose:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check issue
+ uses: tachiyomiorg/issue-moderator-action@v2
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ auto-close-rules: |
+ [
+ {
+ "type": "title",
+ "regex": ".*Short description.*",
+ "message": "You did not fill out the description in the title"
+ }
+ ]
+ auto-close-ignore-label: do-not-autoclose
+ - name: Check PR
+ uses: sumally/github-check-tasklist-action@v1
diff --git a/.github/workflows/lock-closed-issues.yml b/.github/workflows/lock-closed-issues.yml
new file mode 100644
index 0000000000..6b28295e82
--- /dev/null
+++ b/.github/workflows/lock-closed-issues.yml
@@ -0,0 +1,13 @@
+name: Lock closed issue
+
+on:
+ issues:
+ types: [closed]
+
+jobs:
+ lock:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: OSDKDev/lock-issues@v1
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml
new file mode 100644
index 0000000000..d2c2ef42c6
--- /dev/null
+++ b/.github/workflows/lock.yml
@@ -0,0 +1,25 @@
+name: 'Lock Threads'
+
+on:
+ issues:
+ types: [closed]
+ pull_request:
+ types: [closed]
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+
+concurrency:
+ group: lock
+
+jobs:
+ action:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: dessant/lock-threads@v4
+ with:
+ exclude-any-issue-labels: 'do-not-autoclose'
+ exclude-any-pr-labels: 'do-not-autoclose'
+ include-any-pr-labels: 'spam'
diff --git a/.github/workflows/ps2check.yml b/.github/workflows/ps2check.yml
new file mode 100644
index 0000000000..628648806f
--- /dev/null
+++ b/.github/workflows/ps2check.yml
@@ -0,0 +1,27 @@
+name: PSScript checker
+
+on:
+ push:
+ paths:
+ - '**.ps1'
+ - '.github/workflows/ps2check.yml'
+ pull_request:
+ paths:
+ - '**.ps1'
+ - '.github/workflows/ps2check.yml'
+ workflow_dispatch:
+
+jobs:
+ shellcheck:
+ runs-on: windows-latest
+ steps:
+ - name : Checkout
+ uses: actions/checkout@v3
+
+ - name: Run PSScriptAnalyzer
+ uses: microsoft/psscriptanalyzer-action@v1.0
+ with:
+ path: .\installer
+ recurse: true
+ includeDefaultRules: true
+ enableExit: true
diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml
new file mode 100644
index 0000000000..77a79af8f8
--- /dev/null
+++ b/.github/workflows/shellcheck.yml
@@ -0,0 +1,25 @@
+name: Shell checker
+
+on:
+ push:
+ paths:
+ - '**.sh'
+ - '.github/workflows/shellcheck.yml'
+ pull_request:
+ paths:
+ - '**.sh'
+ - '.github/workflows/shellcheck.yml'
+ workflow_dispatch:
+
+jobs:
+ shellcheck:
+ runs-on: ubuntu-latest
+ steps:
+ - name : Checkout
+ uses: actions/checkout@v3
+
+ - name: Run ShellCheck
+ id: check
+ uses: ludeeus/action-shellcheck@master
+ with:
+ scandir: './scripts'
diff --git a/.gitignore b/.gitignore
index f72e5d1ea5..af3808793f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
download
output
+python3-env
+token
diff --git a/Custom-OpenGApps.md b/Custom-OpenGApps.md
deleted file mode 100644
index 8a42afe303..0000000000
--- a/Custom-OpenGApps.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# How to install custom OpenGApps
-
-1. Build WSA without gapps to let the script download needed files
-
- `./build.sh --gapps-brand none`
-1. Place custom OpenGApps to `download` folder and rename to `OpenGApps-{arch}-{variant}.zip` (e.g. `OpenGApps-x64-pico.zip`)
-1. Build WSA offline
-
- `./build.sh --offline --gapps-variant {variant}`
diff --git a/README.md b/README.md
deleted file mode 100644
index b7f50cb191..0000000000
--- a/README.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# Magisk on WSA (with Google Apps)
-
-## Pre-request
-
-- Ubuntu (you can use WSL2)
- - [Search page](https://apps.microsoft.com/store/search?publisher=Canonical%20Group%20Limited)
-
-## Features
-
-- Integrate Magisk and OpenGApps in a few clicks within minutes
-- Keep each build up to date
-- Support both ARM64 and x64
-- Support all OpenGApps variants except for aroma (aroma does not support x86_64, please use super instead)
-- Remove Amazon Appstore
-- Fix VPN dialog not showing (use our [VpnDialogs app](https://github.com/LSPosed/VpnDialogs))
-- Add device management feature
-- Unattended installation
-- Automatically activates developers mode in Windows 11
-- Update to the new version while preserving data with a one-click script
-- Merged all language packs
-- Support managing start menu icons (manually installing [WSAHelper](https://github.com/LSPosed/WSAHelper/releases/latest) to use this feature)
-
-## Text Guide
-
-1. Star (if you like)
-1. Clone the repo to local
-1. Run `scripts/run.sh`
-1. Select the version of Magisk and select the [OpenGApps variant](https://github.com/opengapps/opengapps/wiki#variants) you like, select the root solution (none means no root), select the WSA version and its architecture (mostly x64)
-1. Wait for the script to complete and the artifact will be in the `output` folder
-
-1. Move the artifact to a place you like
-1. Right-click `Install.ps1` and select `Run with PowerShell`
- - If you previously have a MagiskOnWSA installation, it will automatically uninstall the previous one while **preserving all user data** and install the new one, so don't worry about your data.
- - If you have an official WSA installation, you should uninstall it first. (In case you want to preserve your data, you can backup `%LOCALAPPDATA%\Packages\MicrosoftCorporationII.WindowsSubsystemForAndroid_8wekyb3d8bbwe\LocalCache\userdata.vhdx` before uninstallation and restore it after installation.) (If you want to restore the icons to the start menu, please install and use [WSAHelper](https://github.com/LSPosed/WSAHelper/releases/latest).)
- - If the popup windows disappear **without asking administrative permission** and WSA is not installed successfully, you should manually run `Install.ps1` as administrator:
- 1. Press `Win+x` and select `Windows Terminal (Admin)`
- 2. Input `cd "{X:\path\to\your\extracted\folder}"` and press `enter`, and remember to replace `{X:\path\to\your\extracted\folder}` including the `{}`, for example `cd "D:\wsa"`
- 3. Input `PowerShell.exe -ExecutionPolicy Bypass -File .\Install.ps1` and press `enter`
- 4. The script will run and WSA will be installed
- 5. If this workaround does not work, your PC is not supported for WSA
-1. Magisk/Play store will be launched. Enjoy by installing LSPosed-zygisk with zygisk enabled or Riru and LSPosed-riru
-
-## FAQ
-
-- Can I delete the installed folder?
-
- No.
-- How can I update WSA to a new version?
-
- Delete the `download` folder
- Rerun the script, replace the content of your previous installation and rerun `Install.ps1`. Don't worry, your data will be preserved.
-- How can I get the logcat from WSA?
-
- `%LOCALAPPDATA%\Packages\MicrosoftCorporationII.WindowsSubsystemForAndroid_8wekyb3d8bbwe\LocalState\diagnostics\logcat`
-- How can I update Magisk to a new version?
-
- Do the same as updating WSA
-- How to pass safetynet?
-
- Like all the other emulators, no way.
-- Virtualization is not enabled?
-
- `Install.ps1` helps you enable it if not enabled. After rebooting, rerun `Install.ps1` to install WSA. If it's still not working, you have to enable virtualization in BIOS. That's a long story so ask Google for help.
-- How to remount the system as read-write?
-
- No way in WSA since it's mounted as read-only by Hyper-V. You can modify the system by making a Magisk module. Or directly modify the system.img. Ask Google for help.
-- I cannot `adb connect localhost:58526`
-
- Make sure developer mode is enabled. If the issue persists, check the IP address of WSA on the setting page and try `adb connect ip:5555`.
-- Magisk online module list is empty?
-
- Magisk actively removes the online module repository. You can install the module locally or by `adb push module.zip /data/local/tmp` and `adb shell su -c magisk --install-module /data/local/tmp/module.zip`.
-- Can I use Magisk 23.0 stable or a lower version?
-
- No. Magisk has bugs preventing itself from running on WSA. Magisk 24+ has fixed them. So you must use Magisk 24 or higher version.
-- How can I get rid of Magisk?
-
- Choose `none` as the root solution.
-- How to install custom OpenGApps?
-
- [Tutorial](./Custom-OpenGApps.md)
-
-## Credits
-
-- [StoreLib](https://github.com/StoreDev/StoreLib): API for downloading WSA
-- [Magisk](https://github.com/topjohnwu/Magisk): The most famous root solution on Android
-- [The Open GApps Project](https://opengapps.org): One of the most famous Google Apps packages solution
-- [WSA-Kernel-SU](https://github.com/LSPosed/WSA-Kernel-SU) and [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/): The kernel `su` for debugging Magisk Integration
-- [WSAGAScript](https://github.com/ADeltaX/WSAGAScript): The first GApps integration script for WSA
diff --git a/arm64/gapps/priv-app/SetupWizard/SetupWizard.apk b/arm64/gapps/priv-app/SetupWizard/SetupWizard.apk
deleted file mode 100644
index 6fae55f663..0000000000
Binary files a/arm64/gapps/priv-app/SetupWizard/SetupWizard.apk and /dev/null differ
diff --git a/arm64/gapps/product/overlay/GoogleWebViewOverlay.apk b/arm64/gapps/product/overlay/GoogleWebViewOverlay.apk
deleted file mode 100644
index 44ac318b26..0000000000
Binary files a/arm64/gapps/product/overlay/GoogleWebViewOverlay.apk and /dev/null differ
diff --git a/arm64/system/system/etc/permissions/android.software.device_admin.xml b/arm64/system/system/etc/permissions/android.software.device_admin.xml
deleted file mode 100644
index 7d14dc661c..0000000000
--- a/arm64/system/system/etc/permissions/android.software.device_admin.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
diff --git a/arm64/system/system/priv-app/VpnDialogs/VpnDialogs.apk b/arm64/system/system/priv-app/VpnDialogs/VpnDialogs.apk
deleted file mode 100644
index 4179a48238..0000000000
Binary files a/arm64/system/system/priv-app/VpnDialogs/VpnDialogs.apk and /dev/null differ
diff --git a/arm64/system/system/priv-app/WSAHelper/WSAHelper.apk b/arm64/system/system/priv-app/WSAHelper/WSAHelper.apk
deleted file mode 100755
index 9817e059ca..0000000000
Binary files a/arm64/system/system/priv-app/WSAHelper/WSAHelper.apk and /dev/null differ
diff --git a/bin/arm64/lspinit b/bin/arm64/lspinit
new file mode 100644
index 0000000000..89d1a22bc2
Binary files /dev/null and b/bin/arm64/lspinit differ
diff --git a/bin/arm64/makepri.exe b/bin/arm64/makepri.exe
new file mode 100644
index 0000000000..7e9e1a1173
Binary files /dev/null and b/bin/arm64/makepri.exe differ
diff --git a/bin/x64/lspinit b/bin/x64/lspinit
new file mode 100644
index 0000000000..cd9483e180
Binary files /dev/null and b/bin/x64/lspinit differ
diff --git a/bin/x64/makepri.exe b/bin/x64/makepri.exe
new file mode 100644
index 0000000000..47377664a0
Binary files /dev/null and b/bin/x64/makepri.exe differ
diff --git a/docs/Custom-GApps.md b/docs/Custom-GApps.md
new file mode 100644
index 0000000000..ea19f54f2e
--- /dev/null
+++ b/docs/Custom-GApps.md
@@ -0,0 +1,15 @@
+# How to install custom GApps
+
+1. Build WSA without gapps to let the script download needed files
+
+ `./build.sh --gapps-brand none`
+1.
+ - For OpenGApps
+
+ Place custom OpenGApps to `download` folder and rename to `OpenGApps-{arch}-{variant}.zip` (e.g. `OpenGApps-x64-pico.zip`)
+ - For MindTheGapps
+
+ Place custom MindTheGapps to `download` folder and rename to `MindTheGapps-{arch}.zip` (e.g. `MindTheGapps-x64.zip`)
+1. Build WSA offline
+
+ `./build.sh --offline --gapps-brand {brand} --gapps-variant {variant}`
diff --git a/docs/KernelSU.md b/docs/KernelSU.md
new file mode 100644
index 0000000000..d52e80ec21
--- /dev/null
+++ b/docs/KernelSU.md
@@ -0,0 +1,19 @@
+# Install KernelSU
+
+## Install Manager
+
+1. Download KernelSU Manager from [](https://github.com/tiann/KernelSU/actions/workflows/build-manager.yml?query=event%3Apush+is%3Acompleted+branch%3Amain) (Download the artifact named `manager`).
+
+1. Unzip the downloaded zip package and get the manager apk named `KernelSU_vx.x.x-xx-.....apk`.
+
+1. Use the command `adb install .apk` to install the manager.
+
+## Install Kernel
+
+1. Download pre-build kernel from [](https://github.com/tiann/KernelSU/actions/workflows/build-kernel-wsa.yml?query=branch%3Amain+event%3Apush+is%3Acompleted) (Remember to download the same architecture).
+
+1. Unzip the downloaded zip package and get the kernel file named `bzImage`.
+
+1. Replace the kernel in the folder named `Tools` in the WSA directory with `bzImage`.
+
+1. Restart WSA and then enjoy.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000000..a30f026e23
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,181 @@
+# Magisk on WSA (with Google Apps)
+
+:warning: Magisk on WSA will no longer be available after March 5, 2025. [Learn more](https://learn.microsoft.com/en-us/windows/android/wsa/).
+
+:warning: For fork developers: Please don't build using GitHub Actions, as GitHub will count your forked GitHub Actions usage against this upstream repository, which may cause this upstream repository gets disabled by GitHub staff like [MagiskOnWSA](https://github.com/LSPosed/MagiskOnWSA) because of numerous forks building GitHub Actions, and counting the forks' Action usage against this upstream repository.
+
+## Support for generating from these systems
+
+- Linux (x86_64 or arm64)
+
+ The following dependencies are required:
+
+ | DistrOS | | | | | |
+ |:-------------------:|----------------------------|------------|--------------------|---------------|---------------|
+ | Debian | `python3 aria2 unzip sudo` | `whiptail` | `python3-venv` | `python3-pip` | `p7zip-full` |
+ | openSUSE Tumbleweed | Same as above | `dialog` | `python3-venvctrl` | Same as above | Same as above |
+ | Arch | Same as Debian | `libnewt` | Same as Debian | `python-pip` | `p7zip` |
+
+ The python3 library `requests` is used.
+
+ Python version ≥ **3.7.2**.
+
+ - Recommended use
+
+ - Ubuntu (You can use [WSL2](https://apps.microsoft.com/store/search?publisher=Canonical%20Group%20Limited))
+
+ Ready to use right out of the box.
+
+ - Debian (You can use [WSL2](https://apps.microsoft.com/store/detail/debian/9MSVKQC78PK6))
+
+ Ready to use right out of the box.
+
+ - openSUSE Tumbleweed (You can use [WSL2](https://apps.microsoft.com/store/detail/opensuse-tumbleweed/9MSSK2ZXXN11))
+
+ Ready to use right out of the box.
+
+ `run.sh` will handle all dependencies automatically.
+
+ No need to type any commands.
+
+## Features
+
+- Integrate Magisk and GApps in a few clicks within minutes
+- Keep each build up to date
+- Support both ARM64 and x64
+- Support MindTheGapps
+- Remove Amazon Appstore
+- Fix VPN dialog not showing (use our [VpnDialogs app](https://github.com/LSPosed/VpnDialogs))
+- Add device administration feature
+- Unattended installation
+- Automatically activates developers mode in Windows 11
+- Update to the new version while preserving data with a one-click script
+- Merged all language packs
+
+## Text Guide
+
+1. Star (if you like).
+2. Clone the repo to local:
+
+ ```bash
+ git clone https://github.com/LSPosed/MagiskOnWSALocal.git --depth 1
+ ```
+
+3. Run `cd MagiskOnWSALocal`.
+4. Run `./scripts/run.sh`.
+5. Select the WSA version and its architecture (mostly x64).
+6. Select the version of Magisk.
+7. Choose which brand of GApps you want to install:
+ - MindTheGapps
+
+ There is no other variant we can choose.
+8. Select the root solution (none means no root).
+9. If you are running the script for the first time, it will take some time to complete. After the script completes, two new folders named `output` and `download` will be generated in the `MagiskOnWSALocal` folder. Go to the `output` folder. While running the `./run.sh` script in the step 3, if you selected `Yes` for `Do you want to compress the output?` then in `output` folder you will see a compressed file called `WSA-with-magisk-stable-MindTheGapps_2207.40000.8.0_x64_Release-Nightly`or else there will be folder with the `WSA-with-magisk-stable-MindTheGapps_2207.40000.8.0_x64_Release-Nightly`. If there is a folder open it and skip to step 10. NOTE: The name of compressed file or the folder generated in the `output` folder may be different for you. It will be dependent on the choices made when executing `./run.sh`.
+10. Extract the compressed file and open the folder created after the extraction of the file.
+11. Here look for file `Run.bat` and run it.
+ - If you previously have a MagiskOnWSA installation, it will automatically uninstall the previous one while **preserving all user data** and install the new one, so don't worry about your data.
+ - If you have an official WSA installation, you should uninstall it first. (In case you want to preserve your data, you can backup `%LOCALAPPDATA%\Packages\MicrosoftCorporationII.WindowsSubsystemForAndroid_8wekyb3d8bbwe\LocalCache\userdata.vhdx` before uninstallation and restore it after installation.)
+ - If the popup windows disappear **without asking administrative permission** and WSA is not installed successfully, you should manually run `Install.ps1` as Administrator:
+ 1. Press `Win+x` and select `Windows Terminal (Admin)`.
+ 2. Input `cd "{X:\path\to\your\extracted\folder}"` and press `enter`, and remember to replace `{X:\path\to\your\extracted\folder}` including the `{}`, for example `cd "D:\wsa"`
+ 3. Input `PowerShell.exe -ExecutionPolicy Bypass -File .\Install.ps1` and press `Enter`.
+ 4. The script will run and WSA will be installed.
+ 5. If this workaround does not work, your PC is not supported for WSA.
+12. Magisk/Play Store will be launched. Enjoy by installing LSPosed-Zygisk with Zygisk enabled or Riru and LSPosed-Riru.
+
+---
+
+## FAQ
+
+
+
+- Can I delete the installed folder?
+
+ No.
+
+- How can I update WSA to a newer version?
+
+ 1. Update build scripts:
+
+ ```bash
+ git pull
+ ```
+
+ For more usage of git, referred to
+
+ 2. Rerun the script, replace the content of your previous installation and rerun `Install.ps1`. Don't worry, your data will be preserved.
+
+- How can I get the logcat from WSA?
+
+ `%LOCALAPPDATA%\Packages\MicrosoftCorporationII.WindowsSubsystemForAndroid_8wekyb3d8bbwe\LocalState\diagnostics\logcat`
+
+- How can I update Magisk to a newer version?
+
+ Do the same as updating WSA.
+
+- How to pass Play Integrity (formerly known as SafetyNet)?
+
+ Like all the other emulators, no way.
+
+- Virtualization is not enabled?
+
+ `Install.ps1` helps you enable it if not enabled. After rebooting, rerun `Install.ps1` to install WSA. If it's still not working, you have to enable virtualization in BIOS. That's a long story so ask Google for help.
+
+- How to remount the system as read-write?
+
+ No way in WSA since it's mounted as read-only by Hyper-V. You can modify the system by making a Magisk module. Or directly modify the system.img. Ask Google for help.
+
+- I cannot `adb connect localhost:58526`, what to do?
+
+ Make sure developer mode is enabled. If the issue persists, check the IP address of WSA on the setting page and try `adb connect ip:5555`.
+
+- Why the Magisk online module is empty?
+
+ Magisk actively removes the online module repository. You can install the module locally or by `adb push module.zip /data/local/tmp` and `adb shell su -c magisk --install-module /data/local/tmp/module.zip`.
+
+- Can I use Magisk v23.0 stable or a lower version?
+
+ No. Magisk has bugs preventing itself from running on WSA. Magisk v24+ has fixed them. So you must use Magisk v24 or later.
+
+- How can I get rid of Magisk?
+
+ Choose `none` as the root solution.
+
+- How to install custom GApps?
+
+ [Tutorial](Custom-GApps.md)
+
+- Where can I download MindTheGapps?
+
+ You can download from here [MindTheGapps](https://androidfilehost.com/?w=files&flid=322935) ([mirror](http://downloads.codefi.re/jdcteam/javelinanddart/gapps)).
+
+ Note that there is no x86_64 pre-build, so you need to build it by yourself ([Repository](https://gitlab.com/MindTheGapps/vendor_gapps)).
+
+ Or you can download the built package for 12.1 and 13 for x86_64 from [this page](https://sourceforge.net/projects/wsa-mtg/files/x86_64/).
+
+- Is it possible to migrate data from a lower version like 2305 to a newer version?
+
+ This is certainly available, Microsoft's change of read-only partition from 2305's EROFS to read-only EXT4 only affects the read-only system partition.
+
+ It has no effect on the user data partition. Check the logs if there is a failure to boot.
+
+- How to install KernelSU?
+
+ [Tutorial](KernelSU.md)
+
+
+
+---
+
+## Credits
+
+- [StoreLib](https://github.com/StoreDev/StoreLib): API for downloading WSA
+- [Magisk](https://github.com/topjohnwu/Magisk): The most famous root solution on Android
+- ~~[The Open GApps Project](https://opengapps.org): One of the most famous Google Apps packages solution~~
+- [WSA-Kernel-SU](https://github.com/LSPosed/WSA-Kernel-SU) and [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/): The kernel `su` for debugging Magisk Integration
+- ~~[WSAGAScript](https://github.com/ADeltaX/WSAGAScript): The first GApps integration script for WSA~~
+- ~~[erofs-utils](https://github.com/sekaiacg/erofs-utils): Pre-build `erofs-utils` with erofsfuse enabled~~
+
+_The repository is provided as a utility._
+
+_Android is a trademark of Google LLC. Windows is a trademark of Microsoft Corporation._
diff --git a/installer/Install.ps1 b/installer/Install.ps1
new file mode 100644
index 0000000000..afb8626078
--- /dev/null
+++ b/installer/Install.ps1
@@ -0,0 +1,177 @@
+# This file is part of MagiskOnWSALocal.
+#
+# MagiskOnWSALocal is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# MagiskOnWSALocal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with MagiskOnWSALocal. If not, see .
+#
+# Copyright (C) 2024 LSPosed Contributors
+#
+
+$Host.UI.RawUI.WindowTitle = "Installing MagiskOnWSA...."
+function Test-Administrator {
+ [OutputType([bool])]
+ param()
+ process {
+ [Security.Principal.WindowsPrincipal]$user = [Security.Principal.WindowsIdentity]::GetCurrent();
+ return $user.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator);
+ }
+}
+
+function Get-InstalledDependencyVersion {
+ param (
+ [string]$Name,
+ [string]$ProcessorArchitecture
+ )
+ PROCESS {
+ If ($null -Ne $ProcessorArchitecture) {
+ return Get-AppxPackage -Name $Name | ForEach-Object { if ($_.Architecture -Eq $ProcessorArchitecture) { $_ } } | Sort-Object -Property Version | Select-Object -ExpandProperty Version -Last 1;
+ }
+ }
+}
+
+Function Test-CommandExist {
+ Param ($Command)
+ $OldPreference = $ErrorActionPreference
+ $ErrorActionPreference = 'stop'
+ try { if (Get-Command $Command) { RETURN $true } }
+ Catch { RETURN $false }
+ Finally { $ErrorActionPreference = $OldPreference }
+} #end function Test-CommandExist
+
+Function Finish {
+ Clear-Host
+ Start-Process "wsa://com.topjohnwu.magisk"
+ Start-Process "wsa://com.android.vending"
+}
+
+If (Test-CommandExist pwsh.exe) {
+ $pwsh = "pwsh.exe"
+}
+Else {
+ $pwsh = "powershell.exe"
+}
+
+If (-Not (Test-Administrator)) {
+ Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force
+ $Proc = Start-Process -PassThru -Verb RunAs $pwsh -Args "-ExecutionPolicy Bypass -Command Set-Location '$PSScriptRoot'; &'$PSCommandPath' EVAL"
+ If ($null -Ne $Proc) {
+ $Proc.WaitForExit()
+ }
+ If ($null -Eq $Proc -Or $Proc.ExitCode -Ne 0) {
+ Write-Warning "Failed to launch start as Administrator`r`nPress any key to exit"
+ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
+ }
+ exit
+}
+ElseIf (($args.Count -Eq 1) -And ($args[0] -Eq "EVAL")) {
+ Start-Process $pwsh -NoNewWindow -Args "-ExecutionPolicy Bypass -Command Set-Location '$PSScriptRoot'; &'$PSCommandPath'"
+ exit
+}
+
+$FileList = Get-Content -Path .\filelist.txt
+If (((Test-Path -Path $FileList) -Eq $false).Count) {
+ Write-Error "Some files are missing in the folder. Please try to build again. Press any key to exit"
+ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
+ exit 1
+}
+
+If (((Test-Path -Path "MakePri.ps1") -And (Test-Path -Path "makepri.exe")) -Eq $true) {
+ $ProcMakePri = Start-Process $pwsh -PassThru -NoNewWindow -Args "-ExecutionPolicy Bypass -File MakePri.ps1" -WorkingDirectory $PSScriptRoot
+ $null = $ProcMakePri.Handle
+ $ProcMakePri.WaitForExit()
+ If ($ProcMakePri.ExitCode -Ne 0) {
+ Write-Warning "Failed to merge resources, WSA Seetings will always be in English`r`nPress any key to continue"
+ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
+ }
+ $Host.UI.RawUI.WindowTitle = "Installing MagiskOnWSA...."
+}
+
+reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
+
+# When using PowerShell which is installed with MSIX
+# Get-WindowsOptionalFeature and Enable-WindowsOptionalFeature will fail
+# See https://github.com/PowerShell/PowerShell/issues/13866
+if ($PSHOME.contains("8wekyb3d8bbwe")) {
+ Import-Module DISM -UseWindowsPowerShell
+}
+
+If ($(Get-WindowsOptionalFeature -Online -FeatureName 'VirtualMachinePlatform').State -Ne "Enabled") {
+ Enable-WindowsOptionalFeature -Online -NoRestart -FeatureName 'VirtualMachinePlatform'
+ Write-Warning "Need restart to enable virtual machine platform`r`nPress y to restart or press any key to exit"
+ $Key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
+ If ("y" -Eq $Key.Character) {
+ Restart-Computer -Confirm
+ }
+ Else {
+ exit 1
+ }
+}
+
+[xml]$Xml = Get-Content ".\AppxManifest.xml";
+$Name = $Xml.Package.Identity.Name;
+Write-Output "Installing $Name version: $($Xml.Package.Identity.Version)"
+$ProcessorArchitecture = $Xml.Package.Identity.ProcessorArchitecture;
+$Dependencies = $Xml.Package.Dependencies.PackageDependency;
+$Dependencies | ForEach-Object {
+ $InstalledVersion = Get-InstalledDependencyVersion -Name $_.Name -ProcessorArchitecture $ProcessorArchitecture;
+ If ( $InstalledVersion -Lt $_.MinVersion ) {
+ If ($env:WT_SESSION) {
+ $env:WT_SESSION = $null
+ Write-Output "Dependency should be installed but Windows Terminal is in use. Restarting to conhost.exe"
+ Start-Process conhost.exe -Args "powershell.exe -ExecutionPolicy Bypass -Command Set-Location '$PSScriptRoot'; &'$PSCommandPath'"
+ exit 1
+ }
+ Write-Output "Dependency package $($_.Name) $ProcessorArchitecture required minimum version: $($_.MinVersion). Installing...."
+ Add-AppxPackage -ForceApplicationShutdown -ForceUpdateFromAnyVersion -Path "$($_.Name)_$ProcessorArchitecture.appx"
+ }
+ Else {
+ Write-Output "Dependency package $($_.Name) $ProcessorArchitecture current version: $InstalledVersion. Nothing to do."
+ }
+}
+
+$Installed = $null
+$Installed = Get-AppxPackage -Name $Name
+
+If (($null -Ne $Installed) -And (-Not ($Installed.IsDevelopmentMode))) {
+ Write-Warning "There is already one installed WSA. Please uninstall it first.`r`nPress y to uninstall existing WSA or press any key to exit"
+ $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
+ If ("y" -Eq $key.Character) {
+ Clear-Host
+ Remove-AppxPackage -Package $Installed.PackageFullName
+ }
+ Else {
+ exit 1
+ }
+}
+
+If (Test-CommandExist WsaClient) {
+ Write-Output "Shutting down WSA...."
+ Start-Process WsaClient -Wait -Args "/shutdown"
+}
+Stop-Process -Name "WsaClient" -ErrorAction SilentlyContinue
+Write-Output "Installing MagiskOnWSA...."
+Add-AppxPackage -ForceApplicationShutdown -ForceUpdateFromAnyVersion -Register .\AppxManifest.xml
+If ($?) {
+ Finish
+}
+ElseIf ($null -Ne $Installed) {
+ Write-Error "Failed to update.`r`nPress any key to uninstall existing installation while preserving user data.`r`nTake in mind that this will remove the Android apps' icon from the start menu.`r`nIf you want to cancel, close this window now."
+ $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
+ Clear-Host
+ Remove-AppxPackage -PreserveApplicationData -Package $Installed.PackageFullName
+ Add-AppxPackage -ForceApplicationShutdown -ForceUpdateFromAnyVersion -Register .\AppxManifest.xml
+ If ($?) {
+ Finish
+ }
+}
+Write-Output "All Done!`r`nPress any key to exit"
+$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
diff --git a/installer/MakePri.ps1 b/installer/MakePri.ps1
new file mode 100644
index 0000000000..0103a6d959
--- /dev/null
+++ b/installer/MakePri.ps1
@@ -0,0 +1,70 @@
+# This file is part of MagiskOnWSALocal.
+#
+# MagiskOnWSALocal is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# MagiskOnWSALocal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with MagiskOnWSALocal. If not, see .
+#
+# Copyright (C) 2023 LSPosed Contributors
+#
+
+$Host.UI.RawUI.WindowTitle = "Merging resources...."
+If ((Test-Path -Path "pri") -Eq $true -And (Test-Path -Path "xml") -Eq $true) {
+ $AppxManifestFile = ".\AppxManifest.xml"
+ Copy-Item .\resources.pri -Destination ".\pri\resources.pri" | Out-Null
+ $ProcNew = Start-Process -PassThru makepri.exe -NoNewWindow -Args "new /pr .\pri /cf .\xml\priconfig.xml /of .\resources.pri /mn $AppxManifestFile /o"
+ $null = $ProcNew.Handle
+ $ProcNew.WaitForExit()
+ If ($ProcNew.ExitCode -Ne 0) {
+ Write-Warning "Failed to merge resources from pris`r`nTrying to dump pris to priinfo...."
+ New-Item -Path "." -Name "priinfo" -ItemType "directory"
+ Clear-Host
+ $i = 0
+ $PriItem = Get-Item ".\pri\*" -Include "*.pri"
+ Write-Output "Dumping resources...."
+ $Processes = ForEach ($Item in $PriItem) {
+ Start-Process -PassThru -WindowStyle Hidden makepri.exe -Args "dump /if $($Item | Resolve-Path -Relative) /o /es .\pri\resources.pri /of .\priinfo\$($Item.Name).xml /dt detailed"
+ $i = $i + 1
+ $Completed = ($i / $PriItem.count) * 100
+ Write-Progress -Activity "Dumping resources" -Status "Dumping $($Item.Name):" -PercentComplete $Completed
+ }
+ $Processes | Wait-Process
+ Write-Progress -Activity "Dumping resources" -Status "Ready" -Completed
+ Clear-Host
+ Write-Output "Creating pri from dumps...."
+ $ProcNewFromDump = Start-Process -PassThru -NoNewWindow makepri.exe -Args "new /pr .\priinfo /cf .\xml\priconfig.xml /of .\resources.pri /mn $AppxManifestFile /o"
+ $null = $ProcNewFromDump.Handle
+ $ProcNewFromDump.WaitForExit()
+ Remove-Item 'priinfo' -Recurse
+ If ($ProcNewFromDump.ExitCode -Ne 0) {
+ Write-Error "Failed to create resources from priinfos"
+ exit 1
+ }
+ }
+
+ $ProjectXml = [xml](Get-Content $AppxManifestFile)
+ $ProjectResources = $ProjectXml.Package.Resources;
+ $(Get-Item .\xml\* -Exclude "priconfig.xml" -Include "*.xml") | ForEach-Object {
+ $($([xml](Get-Content $_)).Package.Resources.Resource) | ForEach-Object {
+ $ProjectResources.AppendChild($($ProjectXml.ImportNode($_, $true)))
+ }
+ }
+ $ProjectXml.Save($AppxManifestFile)
+ Remove-Item 'pri' -Recurse
+ Set-Content -Path "filelist.txt" -Value (Get-Content -Path "filelist.txt" | Select-String -Pattern '^pri$' -NotMatch)
+ Remove-Item 'xml' -Recurse
+ Set-Content -Path "filelist.txt" -Value (Get-Content -Path "filelist.txt" | Select-String -Pattern '^xml$' -NotMatch)
+ Remove-Item 'makepri.exe'
+ Set-Content -Path "filelist.txt" -Value (Get-Content -Path "filelist.txt" | Select-String -Pattern 'makepri.exe' -NotMatch)
+ Remove-Item $PSCommandPath -Force
+ Set-Content -Path "filelist.txt" -Value (Get-Content -Path "filelist.txt" | Select-String -Pattern 'MakePri.ps1' -NotMatch)
+ exit 0
+}
diff --git a/installer/Run.bat b/installer/Run.bat
new file mode 100644
index 0000000000..f04fee8fab
--- /dev/null
+++ b/installer/Run.bat
@@ -0,0 +1,30 @@
+:: This file is part of MagiskOnWSALocal.
+::
+:: MagiskOnWSALocal is free software: you can redistribute it and/or modify
+:: it under the terms of the GNU Affero General Public License as
+:: published by the Free Software Foundation, either version 3 of the
+:: License, or (at your option) any later version.
+::
+:: MagiskOnWSALocal is distributed in the hope that it will be useful,
+:: but WITHOUT ANY WARRANTY; without even the implied warranty of
+:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+:: GNU Affero General Public License for more details.
+::
+:: You should have received a copy of the GNU Affero General Public License
+:: along with MagiskOnWSALocal. If not, see .
+::
+:: Copyright (C) 2023 LSPosed Contributors
+::
+
+@echo off
+%~d0
+cd "%~dp0"
+if not exist Install.ps1 (
+ echo "Install.ps1" is not found.
+ echo Press any key to exit
+ pause>nul
+ exit 1
+) else (
+ start powershell.exe -ExecutionPolicy Bypass -File .\Install.ps1
+ exit
+)
diff --git a/linker/aarch64/libc.so b/linker/aarch64/libc.so
deleted file mode 100644
index 6f4ec47e24..0000000000
Binary files a/linker/aarch64/libc.so and /dev/null differ
diff --git a/linker/aarch64/libdl.so b/linker/aarch64/libdl.so
deleted file mode 100644
index 15cfd68f0b..0000000000
Binary files a/linker/aarch64/libdl.so and /dev/null differ
diff --git a/linker/aarch64/libm.so b/linker/aarch64/libm.so
deleted file mode 100644
index c129e26384..0000000000
Binary files a/linker/aarch64/libm.so and /dev/null differ
diff --git a/linker/aarch64/linker64 b/linker/aarch64/linker64
deleted file mode 100755
index eeca0b8bc1..0000000000
Binary files a/linker/aarch64/linker64 and /dev/null differ
diff --git a/linker/x86_64/libc.so b/linker/x86_64/libc.so
deleted file mode 100644
index 748c48ca07..0000000000
Binary files a/linker/x86_64/libc.so and /dev/null differ
diff --git a/linker/x86_64/libdl.so b/linker/x86_64/libdl.so
deleted file mode 100644
index 8b24897c51..0000000000
Binary files a/linker/x86_64/libdl.so and /dev/null differ
diff --git a/linker/x86_64/libm.so b/linker/x86_64/libm.so
deleted file mode 100644
index 7bf99e88d0..0000000000
Binary files a/linker/x86_64/libm.so and /dev/null differ
diff --git a/linker/x86_64/linker64 b/linker/x86_64/linker64
deleted file mode 100755
index 894beae3d6..0000000000
Binary files a/linker/x86_64/linker64 and /dev/null differ
diff --git a/scripts/build.sh b/scripts/build.sh
index 58dbf4dca4..4ff2c29085 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2024 LSPosed Contributors
#
if [ ! "$BASH_VERSION" ]; then
@@ -28,30 +28,35 @@ if [ "$HOST_ARCH" != "x86_64" ] && [ "$HOST_ARCH" != "aarch64" ]; then
exit 1
fi
cd "$(dirname "$0")" || exit 1
-trap umount_clean EXIT
+# export TMPDIR=$HOME/.cache/wsa
+if [ "$TMPDIR" ] && [ ! -d "$TMPDIR" ]; then
+ mkdir -p "$TMPDIR"
+fi
WORK_DIR=$(mktemp -d -t wsa-build-XXXXXXXXXX_) || exit 1
+
DOWNLOAD_DIR=../download
DOWNLOAD_CONF_NAME=download.list
-OUTPUT_DIR=../output
-MOUNT_DIR="$WORK_DIR"/system
-umount_clean() {
- if [ -d "$MOUNT_DIR" ]; then
- echo "Cleanup Work Directory"
- if [ -d "$MOUNT_DIR/vendor" ]; then
- sudo umount "$MOUNT_DIR"/vendor
- fi
- if [ -d "$MOUNT_DIR/product" ]; then
- sudo umount "$MOUNT_DIR"/product
- fi
- if [ -d "$MOUNT_DIR/system_ext" ]; then
- sudo umount "$MOUNT_DIR"/system_ext
- fi
- sudo umount "$MOUNT_DIR"
- sudo rm -rf "${WORK_DIR:?}"
- else
- rm -rf "${WORK_DIR:?}"
+PYTHON_VENV_DIR="$(dirname "$PWD")/python3-env"
+
+dir_clean() {
+ rm -rf "${WORK_DIR:?}"
+ if [ "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
+ echo "Cleanup Temp Directory"
+ rm -rf "${TMPDIR:?}"
+ unset TMPDIR
+ fi
+ rm -f "${DOWNLOAD_DIR:?}/$DOWNLOAD_CONF_NAME"
+ if [ "$(python3 -c 'import sys ; print( 1 if sys.prefix != sys.base_prefix else 0 )')" = "1" ]; then
+ echo "deactivate python3 venv"
+ deactivate
fi
}
+trap dir_clean EXIT
+OUTPUT_DIR=../output
+WSA_WORK_ENV="${WORK_DIR:?}/ENV"
+if [ -f "$WSA_WORK_ENV" ]; then rm -f "${WSA_WORK_ENV:?}"; fi
+touch "$WSA_WORK_ENV"
+export WSA_WORK_ENV
clean_download() {
if [ -d "$DOWNLOAD_DIR" ]; then
echo "Cleanup Download Directory"
@@ -62,31 +67,33 @@ clean_download() {
rm -f "${MAGISK_PATH:?}"
fi
if [ "$CLEAN_DOWNLOAD_GAPPS" ]; then
- rm -f "${GAPPS_PATH:?}"
+ rm -f "${GAPPS_IMAGE_PATH:?}"
+ rm -f "${GAPPS_RC_PATH:?}"
+ fi
+ if [ "$CLEAN_DOWNLOAD_KERNELSU" ]; then
+ rm -f "${KERNELSU_PATH:?}"
+ rm -f "${KERNELSU_INFO:?}"
fi
fi
}
abort() {
+ [ "$1" ] && echo -e "ERROR: $1"
echo "Build: an error has occurred, exit"
if [ -d "$WORK_DIR" ]; then
- umount_clean
+ echo -e "\nCleanup Work Directory"
+ dir_clean
fi
clean_download
exit 1
}
trap abort INT TERM
-function Gen_Rand_Str {
- tr -dc 'a-zA-Z0-9' "$KERNELSU_INFO"
+ fi
+ if [ "$HAS_GAPPS" ]; then
+ update_gapps_files_name
+ python3 generateGappsLink.py "$ARCH" "$DOWNLOAD_DIR" "$DOWNLOAD_CONF_NAME" "$ANDROID_API" "$GAPPS_IMAGE_NAME" || abort
+ fi
+ if [ -f "$DOWNLOAD_DIR/$DOWNLOAD_CONF_NAME" ]; then
+ echo "Downloading Artifacts"
+ if ! aria2c --no-conf --log-level=info --log="$DOWNLOAD_DIR/aria2_download.log" -x16 -s16 -j5 -c -R -m0 \
+ --async-dns=false --check-integrity=true --continue=true --allow-overwrite=true --conditional-get=true \
+ -d"$DOWNLOAD_DIR" -i"$DOWNLOAD_DIR/$DOWNLOAD_CONF_NAME"; then
+ abort "We have encountered an error while downloading files."
fi
- else
- echo "The $GAPPS_BRAND zip package does not exist."
- abort
fi
- echo -e "Extract done\n"
fi
-
-echo "Expand images"
-
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/system_ext.img || abort
-SYSTEM_EXT_SIZE=$(($(du --apparent-size -sB512 "$WORK_DIR"/wsa/"$ARCH"/system_ext.img | cut -f1) + 20000))
-if [ -d "$WORK_DIR"/gapps/system_ext ]; then
- SYSTEM_EXT_SIZE=$(( SYSTEM_EXT_SIZE + $(du --apparent-size -sB512 "$WORK_DIR"/gapps/system_ext | cut -f1) ))
-fi
-resize2fs "$WORK_DIR"/wsa/"$ARCH"/system_ext.img "$SYSTEM_EXT_SIZE"s || abort
-
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/product.img || abort
-PRODUCT_SIZE=$(($(du --apparent-size -sB512 "$WORK_DIR"/wsa/"$ARCH"/product.img | cut -f1) + 20000))
-if [ -d "$WORK_DIR"/gapps/product ]; then
- PRODUCT_SIZE=$(( PRODUCT_SIZE + $(du --apparent-size -sB512 "$WORK_DIR"/gapps/product | cut -f1) ))
+declare -A FILES_CHECK_LIST=([xaml_PATH]="$xaml_PATH" [vclibs_PATH]="$vclibs_PATH" [UWPVCLibs_PATH]="$UWPVCLibs_PATH")
+if [ "$ROOT_SOL" = "magisk" ]; then
+ FILES_CHECK_LIST+=(["MAGISK_PATH"]="$MAGISK_PATH" ["CUST_PATH"]="$CUST_PATH")
fi
-resize2fs "$WORK_DIR"/wsa/"$ARCH"/product.img "$PRODUCT_SIZE"s || abort
-
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/system.img || abort
-SYSTEM_SIZE=$(($(du --apparent-size -sB512 "$WORK_DIR"/wsa/"$ARCH"/system.img | cut -f1) + 20000))
-if [ -d "$WORK_DIR"/gapps ]; then
- SYSTEM_SIZE=$(( SYSTEM_SIZE + $(du --apparent-size -sB512 "$WORK_DIR"/gapps | cut -f1) - $(du --apparent-size -sB512 "$WORK_DIR"/gapps/product | cut -f1) ))
- if [ -d "$WORK_DIR"/gapps/system_ext ]; then
- SYSTEM_SIZE=$(( SYSTEM_SIZE - $(du --apparent-size -sB512 "$WORK_DIR"/gapps/system_ext | cut -f1) ))
- fi
-fi
-if [ -d "$WORK_DIR"/magisk ]; then
- SYSTEM_SIZE=$(( SYSTEM_SIZE + $(du --apparent-size -sB512 "$WORK_DIR"/magisk/magisk | cut -f1) ))
+if [ "$ROOT_SOL" = "kernelsu" ]; then
+ update_ksu_zip_name
+ FILES_CHECK_LIST+=(["KERNELSU_PATH"]="$KERNELSU_PATH")
fi
-if [ -f "$MAGISK_PATH" ]; then
- SYSTEM_SIZE=$(( SYSTEM_SIZE + $(du --apparent-size -sB512 "$MAGISK_PATH" | cut -f1) ))
+if [ "$HAS_GAPPS" ]; then
+ update_gapps_files_name
+ FILES_CHECK_LIST+=(["GAPPS_IMAGE_PATH"]="$GAPPS_IMAGE_PATH" ["GAPPS_RC_PATH"]="$GAPPS_RC_PATH")
fi
-if [ -d "../$ARCH/system" ]; then
- SYSTEM_SIZE=$(( SYSTEM_SIZE + $(du --apparent-size -sB512 "../$ARCH/system" | cut -f1) ))
+for i in "${FILES_CHECK_LIST[@]}"; do
+ if [ ! -f "$i" ]; then
+ echo "Offline mode: missing [$i]"
+ FILE_MISSING="1"
+ fi
+done
+if [ "$FILE_MISSING" ]; then
+ abort "Some files are missing"
fi
-resize2fs "$WORK_DIR"/wsa/"$ARCH"/system.img "$SYSTEM_SIZE"s || abort
-
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/vendor.img || abort
-VENDOR_SIZE=$(($(du --apparent-size -sB512 "$WORK_DIR"/wsa/"$ARCH"/vendor.img | cut -f1) + 20000))
-resize2fs "$WORK_DIR"/wsa/"$ARCH"/vendor.img "$VENDOR_SIZE"s || abort
-echo -e "Expand images done\n"
-
-echo "Mount images"
-sudo mkdir "$MOUNT_DIR" || abort
-sudo mount -o loop "$WORK_DIR"/wsa/"$ARCH"/system.img "$MOUNT_DIR" || abort
-sudo mount -o loop "$WORK_DIR"/wsa/"$ARCH"/vendor.img "$MOUNT_DIR"/vendor || abort
-sudo mount -o loop "$WORK_DIR"/wsa/"$ARCH"/product.img "$MOUNT_DIR"/product || abort
-sudo mount -o loop "$WORK_DIR"/wsa/"$ARCH"/system_ext.img "$MOUNT_DIR"/system_ext || abort
-echo -e "done\n"
-
-if [ "$REMOVE_AMAZON" ]; then
- echo "Remove Amazon Appstore"
- find "${MOUNT_DIR:?}"/product/{etc/permissions,etc/sysconfig,framework,priv-app} | grep -e amazon -e venezia | sudo xargs rm -rf
+if [ "$ROOT_SOL" = "magisk" ]; then
+ echo "Extracting Magisk"
+ if [ -f "$MAGISK_PATH" ]; then
+ MAGISK_VERSION_NAME=""
+ MAGISK_VERSION_CODE=0
+ if ! python3 extractMagisk.py "$ARCH" "$MAGISK_PATH" "$WORK_DIR"; then
+ CLEAN_DOWNLOAD_MAGISK=1
+ abort "Unzip Magisk failed, is the download incomplete?"
+ fi
+ # shellcheck disable=SC1090
+ source "$WSA_WORK_ENV" || abort
+ if [ "$MAGISK_VERSION_CODE" -lt 26000 ] && [ "$MAGISK_VER" != "stable" ] && [ -z ${CUSTOM_MAGISK+x} ]; then
+ abort "Please install Magisk 26.0+"
+ fi
+ chmod +x "$WORK_DIR/magisk/magiskboot" || abort
+ elif [ -z "${CUSTOM_MAGISK+x}" ]; then
+ abort "The Magisk zip package does not exist, is the download incomplete?"
+ else
+ abort "The Magisk zip package does not exist, rename it to magisk-debug.zip and put it in the download folder."
+ fi
echo -e "done\n"
fi
-if [ "$ROOT_SOL" = 'magisk' ] || [ "$ROOT_SOL" = '' ]; then
- echo "Integrate Magisk"
- sudo mkdir "$MOUNT_DIR"/sbin
- sudo chcon --reference "$MOUNT_DIR"/init.environ.rc "$MOUNT_DIR"/sbin
- sudo chown root:root "$MOUNT_DIR"/sbin
- sudo chmod 0700 "$MOUNT_DIR"/sbin
- sudo cp "$WORK_DIR"/magisk/magisk/* "$MOUNT_DIR"/sbin/
- sudo cp "$MAGISK_PATH" "$MOUNT_DIR"/sbin/magisk.apk
- sudo tee -a "$MOUNT_DIR"/sbin/loadpolicy.sh <
-
-
-
-
-
-
-EOF
-wine64 ../wine/"$HOST_ARCH"/makepri.exe new /pr "$WORK_DIR"/wsa/pri /in MicrosoftCorporationII.WindowsSubsystemForAndroid /cf "$WORK_DIR"/wsa/priconfig.xml /of "$WORK_DIR"/wsa/"$ARCH"/resources.pri /o
-sed -i -zE "s//\n$(cat "$WORK_DIR"/wsa/xml/* | grep -Po ']*/>' | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/\$/\\$/g' | sed 's/\//\\\//g')\n<\/Resources>/g" "$WORK_DIR"/wsa/"$ARCH"/AppxManifest.xml
-echo -e "Merge Language Resources done\n"
-
-echo "Add extra packages"
-sudo cp -r ../"$ARCH"/system/* "$MOUNT_DIR" || abort
-find ../"$ARCH"/system/system/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/priv-app/dir -type d -exec chmod 0755 {} \;
-find ../"$ARCH"/system/system/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/priv-app/dir -type f -exec chmod 0644 {} \;
-find ../"$ARCH"/system/system/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/priv-app/dir -exec chown root:root {} \;
-find ../"$ARCH"/system/system/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/priv-app/dir -exec chcon --reference="$MOUNT_DIR"/system/priv-app {} \;
-find ../"$ARCH"/system/system/etc/permissions/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/etc/permissions/file -type f -exec chmod 0644 {} \;
-find ../"$ARCH"/system/system/etc/permissions/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/etc/permissions/file -exec chown root:root {} \;
-find ../"$ARCH"/system/system/etc/permissions/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/etc/permissions/file -type f -exec chcon --reference="$MOUNT_DIR"/system/etc/permissions/platform.xml {} \;
-echo -e "Add extra packages done\n"
-
-if [ "$GAPPS_BRAND" != 'none' ]; then
- echo "Integrate GApps"
-
- find "$WORK_DIR/gapps/" -mindepth 1 -type d -exec sudo chmod 0755 {} \;
- find "$WORK_DIR/gapps/" -mindepth 1 -type d -exec sudo chown root:root {} \;
- file_list="$(find "$WORK_DIR/gapps/" -mindepth 1 -type f | cut -d/ -f5-)"
- for file in $file_list; do
- sudo chown root:root "$WORK_DIR/gapps/${file}"
- sudo chmod 0644 "$WORK_DIR/gapps/${file}"
- done
-
- if [ "$GAPPS_BRAND" = "OpenGApps" ]; then
- find "$WORK_DIR"/gapps/ -maxdepth 1 -mindepth 1 -type d -not -path '*product' -exec sudo cp --preserve=all -r {} "$MOUNT_DIR"/system \; || abort
- elif [ "$GAPPS_BRAND" = "MindTheGapps" ]; then
- sudo cp --preserve=all -r "$WORK_DIR"/gapps/system_ext/* "$MOUNT_DIR"/system_ext/ || abort
- if [ -e "$MOUNT_DIR"/system_ext/priv-app/SetupWizard ]; then
- rm -rf "${MOUNT_DIR:?}/system_ext/priv-app/Provision"
- fi
+ if [ -f "$WORK_DIR/magisk/init-ld" ]; then
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$WORK_DIR/magisk/init-ld" "$WORK_DIR/magisk/init-ld.xz"
+ unset SKIPINITLD
fi
- sudo cp --preserve=all -r "$WORK_DIR"/gapps/product/* "$MOUNT_DIR"/product || abort
-
- find "$WORK_DIR"/gapps/product/overlay -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/product/overlay/file -type f -exec chcon --reference="$MOUNT_DIR"/product/overlay/FontNotoSerifSource/FontNotoSerifSourceOverlay.apk {} \;
-
- if [ "$GAPPS_BRAND" = "OpenGApps" ]; then
- find "$WORK_DIR"/gapps/app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/app/dir -type d -exec chcon --reference="$MOUNT_DIR"/system/app {} \;
- find "$WORK_DIR"/gapps/framework/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/framework/dir -type d -exec chcon --reference="$MOUNT_DIR"/system/framework {} \;
- find "$WORK_DIR"/gapps/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/priv-app/dir -type d -exec chcon --reference="$MOUNT_DIR"/system/priv-app {} \;
- find "$WORK_DIR"/gapps/app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/app/file -type f -exec chcon --reference="$MOUNT_DIR"/system/app/KeyChain/KeyChain.apk {} \;
- find "$WORK_DIR"/gapps/framework/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/framework/file -type f -exec chcon --reference="$MOUNT_DIR"/system/framework/ext.jar {} \;
- find "$WORK_DIR"/gapps/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system/priv-app/file -type f -exec chcon --reference="$MOUNT_DIR"/system/priv-app/Shell/Shell.apk {} \;
- find "$WORK_DIR"/gapps/etc/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/etc/dir -type d -exec chcon --reference="$MOUNT_DIR"/system/etc/permissions {} \;
- find "$WORK_DIR"/gapps/etc/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system/etc/dir -type f -exec chcon --reference="$MOUNT_DIR"/system/etc/permissions {} \;
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$MAGISK_PATH" "$WORK_DIR/magisk/stub.xz"
+ "$WORK_DIR/magisk/magiskboot" cpio "$WORK_DIR/wsa/$ARCH/Tools/initrd.img" \
+ "mv /init /wsainit" \
+ "add 0750 /lspinit ../bin/$ARCH/lspinit" \
+ "ln /lspinit /init" \
+ "add 0750 /magiskinit $WORK_DIR/magisk/magiskinit" \
+ "mkdir 0750 overlay.d" \
+ "mkdir 0750 overlay.d/sbin" \
+ "$SINGLEABI add 0644 overlay.d/sbin/magisk64.xz $WORK_DIR/magisk/magisk64.xz" \
+ "$SINGLEABI add 0644 overlay.d/sbin/magisk32.xz $WORK_DIR/magisk/magisk32.xz" \
+ "$SKIP add 0644 overlay.d/sbin/magisk.xz $WORK_DIR/magisk/magisk.xz" \
+ "$SKIPINITLD add 0644 overlay.d/sbin/init-ld.xz $WORK_DIR/magisk/init-ld.xz" \
+ "add 0644 overlay.d/sbin/stub.xz $WORK_DIR/magisk/stub.xz" \
+ "mkdir 000 .backup" \
+ "add 000 overlay.d/init.lsp.magisk.rc init.lsp.magisk.rc" \
+ "add 000 overlay.d/sbin/post-fs-data.sh post-fs-data.sh" \
+ "add 000 overlay.d/sbin/lsp_cust.img $CUST_PATH" \
+ || abort "Unable to patch initrd"
+elif [ "$ROOT_SOL" = "kernelsu" ]; then
+ echo "Extracting KernelSU"
+ # shellcheck disable=SC1090
+ source "${KERNELSU_INFO:?}" || abort
+ echo "WSA Kernel Version: $KERNEL_VER"
+ echo "KernelSU Version: $KERNELSU_VER"
+ if ! unzip "$KERNELSU_PATH" -d "$WORK_DIR/kernelsu"; then
+ CLEAN_DOWNLOAD_KERNELSU=1
+ abort "Unzip KernelSU failed, package is corrupted?"
+ fi
+ if [ "$ARCH" = "x64" ]; then
+ mv "$WORK_DIR/kernelsu/bzImage" "$WORK_DIR/kernelsu/kernel"
+ elif [ "$ARCH" = "arm64" ]; then
+ mv "$WORK_DIR/kernelsu/Image" "$WORK_DIR/kernelsu/kernel"
+ fi
+ echo "Integrate KernelSU"
+ mv "$WORK_DIR/wsa/$ARCH/Tools/kernel" "$WORK_DIR/wsa/$ARCH/Tools/kernel_origin"
+ cp "$WORK_DIR/kernelsu/kernel" "$WORK_DIR/wsa/$ARCH/Tools/kernel"
+fi
+echo -e "done\n"
+if [ "$HAS_GAPPS" ]; then
+ update_gapps_files_name
+ if [ -f "$GAPPS_IMAGE_PATH" ] && [ -f "$GAPPS_RC_PATH" ]; then
+ echo "Integrating GApps"
+ "$WORK_DIR/magisk/magiskboot" cpio "$WORK_DIR/wsa/$ARCH/Tools/initrd.img" \
+ "add 000 overlay.d/gapps.rc $GAPPS_RC_PATH" \
+ "add 000 overlay.d/sbin/lsp_gapps.img $GAPPS_IMAGE_PATH" \
+ || abort "Unable to patch initrd"
+ echo -e "done\n"
else
- find "$WORK_DIR"/gapps/product/app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/app/item -type d -exec chcon --reference="$MOUNT_DIR"/product/app {} \;
- find "$WORK_DIR"/gapps/product/etc/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/etc/item -type d -exec chcon --reference="$MOUNT_DIR"/product/etc {} \;
- find "$WORK_DIR"/gapps/product/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/priv-app/item -type d -exec chcon --reference="$MOUNT_DIR"/product/priv-app {} \;
- find "$WORK_DIR"/gapps/product/framework/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/framework/item -type d -exec chcon --reference="$MOUNT_DIR"/product/framework {} \;
-
- find "$WORK_DIR"/gapps/product/app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/app/item -type f -exec chcon --reference="$MOUNT_DIR"/product/app/HomeApp/HomeApp.apk {} \;
- find "$WORK_DIR"/gapps/product/etc/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/etc/item -type f -exec chcon --reference="$MOUNT_DIR"/product/etc/permissions/com.android.settings.intelligence.xml {} \;
- find "$WORK_DIR"/gapps/product/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/priv-app/item -type f -exec chcon --reference="$MOUNT_DIR"/product/priv-app/SettingsIntelligence/SettingsIntelligence.apk {} \;
- find "$WORK_DIR"/gapps/product/framework/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I item sudo find "$MOUNT_DIR"/product/framework/item -type f -exec chcon --reference="$MOUNT_DIR"/product/etc/permissions/com.android.settings.intelligence.xml {} \;
- find "$WORK_DIR"/gapps/system_ext/etc/permissions/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/system_ext/etc/permissions/file -type f -exec chcon --reference="$MOUNT_DIR"/system_ext/etc/permissions/com.android.systemui.xml {} \;
-
- sudo chcon --reference="$MOUNT_DIR"/product/lib64/libjni_eglfence.so "$MOUNT_DIR"/product/lib
- find "$WORK_DIR"/gapps/product/lib/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/product/lib/file -exec chcon --reference="$MOUNT_DIR"/product/lib64/libjni_eglfence.so {} \;
- find "$WORK_DIR"/gapps/product/lib64/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I file sudo find "$MOUNT_DIR"/product/lib64/file -type f -exec chcon --reference="$MOUNT_DIR"/product/lib64/libjni_eglfence.so {} \;
- find "$WORK_DIR"/gapps/system_ext/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system_ext/priv-app/dir -type d -exec chcon --reference="$MOUNT_DIR"/system_ext/priv-app {} \;
- find "$WORK_DIR"/gapps/system_ext/etc/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system_ext/etc/dir -type d -exec chcon --reference="$MOUNT_DIR"/system_ext/etc {} \;
- find "$WORK_DIR"/gapps/system_ext/priv-app/ -maxdepth 1 -mindepth 1 -printf '%P\n' | xargs -I dir sudo find "$MOUNT_DIR"/system_ext/priv-app/dir -type f -exec chcon --reference="$MOUNT_DIR"/system_ext/priv-app/Settings/Settings.apk {} \;
+ abort "The GApps package does not exist."
fi
-
- sudo patchelf --replace-needed libc.so "../linker/$HOST_ARCH/libc.so" "$WORK_DIR"/magisk/magiskpolicy || abort
- sudo patchelf --replace-needed libm.so "../linker/$HOST_ARCH/libm.so" "$WORK_DIR"/magisk/magiskpolicy || abort
- sudo patchelf --replace-needed libdl.so "../linker/$HOST_ARCH/libdl.so" "$WORK_DIR"/magisk/magiskpolicy || abort
- sudo patchelf --set-interpreter "../linker/$HOST_ARCH/linker64" "$WORK_DIR"/magisk/magiskpolicy || abort
- chmod +x "$WORK_DIR"/magisk/magiskpolicy || abort
- sudo "$WORK_DIR"/magisk/magiskpolicy --load "$MOUNT_DIR"/vendor/etc/selinux/precompiled_sepolicy --save "$MOUNT_DIR"/vendor/etc/selinux/precompiled_sepolicy "allow gmscore_app gmscore_app vsock_socket { create connect write read }" "allow gmscore_app device_config_runtime_native_boot_prop file read" "allow gmscore_app system_server_tmpfs dir search" "allow gmscore_app system_server_tmpfs file open" || abort
- echo -e "Integrate GApps done\n"
fi
-if [ "$GAPPS_BRAND" != 'none' ]; then
- echo "Fix GApps prop"
- sudo python3 fixGappsProp.py "$MOUNT_DIR" || abort
- echo -e "done\n"
+if [ "$REMOVE_AMAZON" ]; then
+ rm -f "$WORK_DIR/wsa/$ARCH/apex/"mado*.apex || abort
fi
-echo "Umount images"
-sudo find "$MOUNT_DIR" -exec touch -hamt 200901010000.00 {} \;
-sudo umount "$MOUNT_DIR"/vendor
-sudo umount "$MOUNT_DIR"/product
-sudo umount "$MOUNT_DIR"/system_ext
-sudo umount "$MOUNT_DIR"
+echo "Removing signature and add scripts"
+rm -rf "${WORK_DIR:?}"/wsa/"$ARCH"/\[Content_Types\].xml "$WORK_DIR/wsa/$ARCH/AppxBlockMap.xml" "$WORK_DIR/wsa/$ARCH/AppxSignature.p7x" "$WORK_DIR/wsa/$ARCH/AppxMetadata" || abort
+cp "$vclibs_PATH" "$xaml_PATH" "$WORK_DIR/wsa/$ARCH" || abort
+cp "$UWPVCLibs_PATH" "$xaml_PATH" "$WORK_DIR/wsa/$ARCH" || abort
+cp "../bin/$ARCH/makepri.exe" "$WORK_DIR/wsa/$ARCH" || abort
+cp "../xml/priconfig.xml" "$WORK_DIR/wsa/$ARCH/xml/" || abort
+cp ../installer/MakePri.ps1 "$WORK_DIR/wsa/$ARCH" || abort
+cp ../installer/Install.ps1 "$WORK_DIR/wsa/$ARCH" || abort
+cp ../installer/Run.bat "$WORK_DIR/wsa/$ARCH" || abort
+find "$WORK_DIR/wsa/$ARCH" -maxdepth 1 -mindepth 1 -printf "%P\n" >"$WORK_DIR/wsa/$ARCH/filelist.txt" || abort
echo -e "done\n"
-echo "Shrink images"
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/system.img || abort
-resize2fs -M "$WORK_DIR"/wsa/"$ARCH"/system.img || abort
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/vendor.img || abort
-resize2fs -M "$WORK_DIR"/wsa/"$ARCH"/vendor.img || abort
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/product.img || abort
-resize2fs -M "$WORK_DIR"/wsa/"$ARCH"/product.img || abort
-e2fsck -yf "$WORK_DIR"/wsa/"$ARCH"/system_ext.img || abort
-resize2fs -M "$WORK_DIR"/wsa/"$ARCH"/system_ext.img || abort
-echo -e "Shrink images done\n"
-
-echo "Remove signature and add scripts"
-sudo rm -rf "${WORK_DIR:?}"/wsa/"$ARCH"/\[Content_Types\].xml "$WORK_DIR"/wsa/"$ARCH"/AppxBlockMap.xml "$WORK_DIR"/wsa/"$ARCH"/AppxSignature.p7x "$WORK_DIR"/wsa/"$ARCH"/AppxMetadata || abort
-cp "$vclibs_PATH" "$xaml_PATH" "$WORK_DIR"/wsa/"$ARCH" || abort
-tee "$WORK_DIR"/wsa/"$ARCH"/Install.ps1 <.
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2024 LSPosed Contributors
#
import sys
-
import zipfile
-import os
from pathlib import Path
import platform
+import os
+from typing import Any, OrderedDict
+
+
+class Prop(OrderedDict):
+ def __init__(self, props: str = ...) -> None:
+ super().__init__()
+ for i, line in enumerate(props.splitlines(False)):
+ if '=' in line:
+ k, v = line.split('=', 1)
+ self[k] = v
+ else:
+ self[f".{i}"] = line
+
+ def __setattr__(self, __name: str, __value: Any) -> None:
+ self[__name] = __value
+
+ def __repr__(self):
+ return '\n'.join(f'{item}={self[item]}' for item in self)
+
is_x86_64 = platform.machine() in ("AMD64", "x86_64")
host_abi = "x64" if is_x86_64 else "arm64"
arch = sys.argv[1]
magisk_zip = sys.argv[2]
-if not os.path.exists(Path.cwd().parent / sys.argv[3] / "magisk"):
- os.makedirs(Path.cwd().parent / sys.argv[3] / "magisk")
-workdir = Path.cwd().parent / sys.argv[3] / "magisk"
+workdir = Path(sys.argv[3])
+workdir.mkdir(parents=True, exist_ok=True)
abi_map = {"x64": ["x86_64", "x86"], "arm64": ["arm64-v8a", "armeabi-v7a"]}
+
def extract_as(zip, name, as_name, dir):
info = zip.getinfo(name)
info.filename = as_name
zip.extract(info, workdir / dir)
+
with zipfile.ZipFile(magisk_zip) as zip:
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libmagisk64.so", "magisk64", "magisk")
- extract_as(
- zip, f"lib/{ abi_map[arch][1] }/libmagisk32.so", "magisk32", "magisk")
- standalone_policy = False
- try:
- zip.getinfo(f"lib/{ abi_map[arch][0] }/libmagiskpolicy.so")
- standalone_policy = True
- except:
- pass
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libmagiskinit.so", "magiskinit", "magisk")
- if standalone_policy:
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libmagiskpolicy.so", "magiskpolicy", "magisk")
- else:
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libmagiskinit.so", "magiskpolicy", "magisk")
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libmagiskboot.so", "magiskboot", "magisk")
- extract_as(
- zip, f"lib/{ abi_map[arch][0] }/libbusybox.so", "busybox", "magisk")
- if standalone_policy:
- extract_as(
- zip, f"lib/{ abi_map[host_abi][0] }/libmagiskpolicy.so", "magiskpolicy", ".")
+ props = Prop(zip.comment.decode().replace('\000', '\n'))
+ namelist = zip.namelist()
+ versionName = props.get("version")
+ versionCode = props.get("versionCode")
+ print(f"Magisk version: {versionName} ({versionCode})", flush=True)
+ if 'WSA_WORK_ENV' in os.environ and Path(os.environ['WSA_WORK_ENV']).is_file():
+ with open(os.environ['WSA_WORK_ENV'], 'r') as environ_file:
+ env = Prop(environ_file.read())
+ env.MAGISK_VERSION_NAME = versionName
+ env.MAGISK_VERSION_CODE = versionCode
+ with open(os.environ['WSA_WORK_ENV'], 'w') as environ_file:
+ environ_file.write(str(env))
+ if f"lib/{ abi_map[arch][0] }/libmagisk64.so" in namelist:
+ extract_as(zip, f"lib/{ abi_map[arch][0] }/libmagisk64.so", "magisk64", "magisk")
+ extract_as(zip, f"lib/{ abi_map[arch][1] }/libmagisk32.so", "magisk32", "magisk")
else:
- extract_as(
- zip, f"lib/{ abi_map[host_abi][0] }/libmagiskinit.so", "magiskpolicy", ".")
- extract_as(zip, f"assets/boot_patch.sh", "boot_patch.sh", "magisk")
- extract_as(zip, f"assets/util_functions.sh",
- "util_functions.sh", "magisk")
+ extract_as(zip, f"lib/{ abi_map[arch][0] }/libmagisk.so", "magisk", "magisk")
+ if f"lib/{ abi_map[arch][0] }/libinit-ld.so" in namelist:
+ extract_as(zip, f"lib/{ abi_map[arch][0] }/libinit-ld.so", "init-ld", "magisk")
+ extract_as(zip, f"lib/{ abi_map[arch][0] }/libmagiskinit.so", "magiskinit", "magisk")
+ extract_as(zip, f"lib/{ abi_map[host_abi][0] }/libmagiskboot.so", "magiskboot", "magisk")
diff --git a/scripts/extractWSA.py b/scripts/extractWSA.py
index 9da9204e6e..034d51bc99 100644
--- a/scripts/extractWSA.py
+++ b/scripts/extractWSA.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#
# This file is part of MagiskOnWSALocal.
#
@@ -15,58 +15,98 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2023 LSPosed Contributors
#
+import os
import sys
+from typing import Any, OrderedDict
-import warnings
import zipfile
-import os
from pathlib import Path
+import re
+import shutil
+
+
+class Prop(OrderedDict):
+ def __init__(self, props: str = ...) -> None:
+ super().__init__()
+ for i, line in enumerate(props.splitlines(False)):
+ if '=' in line:
+ k, v = line.split('=', 1)
+ self[k] = v
+ else:
+ self[f".{i}"] = line
+
+ def __setattr__(self, __name: str, __value: Any) -> None:
+ self[__name] = __value
+
+ def __repr__(self):
+ return '\n'.join(f'{item}={self[item]}' for item in self)
-warnings.filterwarnings("ignore")
arch = sys.argv[1]
-if not os.path.exists(Path.cwd().parent / sys.argv[2] / "wsa"):
- os.makedirs(Path.cwd().parent / sys.argv[2] / "wsa")
zip_name = ""
-wsa_zip_path= Path(sys.argv[2]).resolve()
-workdir = Path.cwd().parent / sys.argv[3] / "wsa"
+wsa_zip_path = Path(sys.argv[2])
+rootdir = Path(sys.argv[3])
+env_file = Path(sys.argv[4])
+
+workdir = rootdir / "wsa"
+archdir = Path(workdir / arch)
+pridir = workdir / archdir / 'pri'
+xmldir = workdir / archdir / 'xml'
+if not Path(rootdir).is_dir():
+ rootdir.mkdir()
+
+if Path(workdir).is_dir():
+ shutil.rmtree(workdir)
+else:
+ workdir.unlink(missing_ok=True)
+
+if not Path(workdir).is_dir():
+ workdir.mkdir()
+
+if not Path(archdir).is_dir():
+ archdir.mkdir()
+uid = os.getuid()
+workdir_rw = os.access(workdir, os.W_OK)
+
with zipfile.ZipFile(wsa_zip_path) as zip:
for f in zip.filelist:
- if arch in f.filename.lower():
+ filename_lower = f.filename.lower()
+ if arch in filename_lower:
zip_name = f.filename
- output_name = zip_name[11:-5]
- if not os.path.isfile(workdir / zip_name):
- zip_path = workdir / zip_name
- print(f"unzipping to {workdir}", flush=True)
- zip.extract(f, workdir)
+ if not Path(workdir / zip_name).is_file():
+ print(f"unzipping {zip_name} to {workdir}", flush=True)
+ zip_path = zip.extract(f, workdir)
+ with zipfile.ZipFile(zip_path) as wsa_zip:
+ stat = Path(zip_path).stat()
+ print(f"unzipping from {zip_path}", flush=True)
+ wsa_zip.extractall(archdir)
ver_no = zip_name.split("_")
long_ver = ver_no[1]
ver = long_ver.split(".")
- main_ver = ver[0]
- with open(os.environ['WSA_WORK_ENV'], 'a') as g:
- g.write(f'WSA_VER={long_ver}\n')
- with open(os.environ['WSA_WORK_ENV'], 'a') as g:
- g.write(f'WSA_MAIN_VER={main_ver}\n')
+ major_ver = ver[0]
rel = ver_no[3].split(".")
- rell = str(rel[0])
- with open(os.environ['WSA_WORK_ENV'], 'a') as g:
- g.write(f'WSA_REL={rell}\n')
- if 'language' in f.filename.lower() or 'scale' in f.filename.lower():
- name = f.filename.split("-", 1)[1].split(".")[0]
+ rel_long = str(rel[0])
+ with open(env_file, 'r') as environ_file:
+ env = Prop(environ_file.read())
+ env.WSA_VER = long_ver
+ env.WSA_MAJOR_VER = major_ver
+ env.WSA_REL = rel_long
+ with open(env_file, 'w') as environ_file:
+ environ_file.write(str(env))
+ if 'language' in filename_lower or 'scale' in filename_lower:
+ name = f.filename.split("_")[2].split(".")[0]
zip.extract(f, workdir)
with zipfile.ZipFile(workdir / f.filename) as l:
for g in l.filelist:
if g.filename == 'resources.pri':
- g.filename = f'{name}.pri'
- l.extract(g, workdir / 'pri')
+ g.filename = f'resources.{name}.pri'
+ l.extract(g, pridir)
elif g.filename == 'AppxManifest.xml':
- g.filename = f'{name}.xml'
- l.extract(g, workdir / 'xml')
-with zipfile.ZipFile(zip_path) as zip:
- if not os.path.isdir(workdir / arch):
- print(f"unzipping from {zip_path}", flush=True)
- zip.extractall(workdir / arch)
+ g.filename = f'resources.{name}.xml'
+ l.extract(g, xmldir)
+ elif re.search(r'Images/.+\.png', g.filename):
+ l.extract(g, archdir)
diff --git a/scripts/fixGappsProp.py b/scripts/fixGappsProp.py
deleted file mode 100644
index 0bd7dcee03..0000000000
--- a/scripts/fixGappsProp.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python
-#
-# This file is part of MagiskOnWSALocal.
-#
-# MagiskOnWSALocal is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# MagiskOnWSALocal is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with MagiskOnWSALocal. If not, see .
-#
-# Copyright (C) 2022 LSPosed Contributors
-#
-
-from __future__ import annotations
-from io import TextIOWrapper
-from os import system, path
-from typing import OrderedDict
-import sys
-class Prop(OrderedDict):
- def __init__(self, file: TextIOWrapper) -> None:
- super().__init__()
- for i, line in enumerate(file.read().splitlines(False)):
- if '=' in line:
- k, v = line.split('=', 2)
- self[k] = v
- else:
- self[f".{i}"] = line
-
- def __str__(self) -> str:
- return '\n'.join([v if k.startswith('.') else f"{k}={v}" for k, v in self.items()])
-
- def __iadd__(self, other: str) -> Prop:
- self[f".{len(self)}"] = other
- return self
-
-
-new_props = {
- ("product", "brand"): "google",
- ("product", "manufacturer"): "Google",
- ("build", "product"): "redfin",
- ("product", "name"): "redfin",
- ("product", "device"): "redfin",
- ("product", "model"): "Pixel 5",
- ("build", "flavor"): "redfin-user"
-}
-
-
-def description(sec: str, p: Prop) -> str:
- return f"{p[f'ro.{sec}.build.flavor']} {p[f'ro.{sec}.build.version.release_or_codename']} {p[f'ro.{sec}.build.id']} {p[f'ro.{sec}.build.version.incremental']} {p[f'ro.{sec}.build.tags']}"
-
-
-def fingerprint(sec: str, p: Prop) -> str:
- return f"""{p[f"ro.product.{sec}.brand"]}/{p[f"ro.product.{sec}.name"]}/{p[f"ro.product.{sec}.device"]}:{p[f"ro.{sec}.build.version.release"]}/{p[f"ro.{sec}.build.id"]}/{p[f"ro.{sec}.build.version.incremental"]}:{p[f"ro.{sec}.build.type"]}/{p[f"ro.{sec}.build.tags"]}"""
-
-
-def fix_prop(sec, prop):
- if not path.exists(prop):
- return
-
- print(f"fixing {prop}", flush=True)
- with open(prop, 'r') as f:
- p = Prop(f)
-
- p += "# extra prop added by MagiskOnWSA"
-
- for k, v in new_props.items():
- p[f"ro.{k[0]}.{k[1]}"] = v
-
- if k[0] == "build":
- p[f"ro.{sec}.{k[0]}.{k[1]}"] = v
- elif k[0] == "product":
- p[f"ro.{k[0]}.{sec}.{k[1]}"] = v
-
- p["ro.build.description"] = description(sec, p)
- p[f"ro.build.fingerprint"] = fingerprint(sec, p)
- p[f"ro.{sec}.build.description"] = description(sec, p)
- p[f"ro.{sec}.build.fingerprint"] = fingerprint(sec, p)
- p[f"ro.bootimage.build.fingerprint"] = fingerprint(sec, p)
-
- with open(prop, 'w') as f:
- f.write(str(p))
-
-
-sys_path = sys.argv[1]
-for sec, prop in {"system": sys_path+"/system/build.prop", "product": sys_path+"/product/build.prop", "system_ext": sys_path+"/system_ext/build.prop", "vendor": sys_path+"/vendor/build.prop", "odm": sys_path+"/vendor/odm/etc/build.prop"}.items():
- fix_prop(sec, prop)
diff --git a/scripts/generateGappsLink.py b/scripts/generateGappsLink.py
index 06cc5598cb..ecb77798d2 100644
--- a/scripts/generateGappsLink.py
+++ b/scripts/generateGappsLink.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#
# This file is part of MagiskOnWSALocal.
#
@@ -15,43 +15,65 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2024 LSPosed Contributors
#
+from datetime import datetime
import sys
import requests
-import os
import json
import re
from pathlib import Path
-arch = sys.argv[1]
-variant = sys.argv[2]
-download_dir = Path.cwd().parent / "download" if sys.argv[3] == "" else Path(sys.argv[3]).resolve()
-tempScript = sys.argv[4]
-print(f"Generating OpenGApps download link: arch={arch} variant={variant}", flush=True)
-abi_map = {"x64": "x86_64", "arm64": "arm64"}
-# TODO: keep it 11.0 since opengapps does not support 12+ yet
-# As soon as opengapps is available for 12+, we need to get the sdk/release from build.prop and
-# download the corresponding version
-release = "11.0"
-try:
- res = requests.get(f"https://api.opengapps.org/list")
- j = json.loads(res.content)
- link = {i["name"]: i for i in j["archs"][abi_map[arch]]
- ["apis"][release]["variants"]}[variant]["zip"]
-except Exception:
- print("Failed to fetch from OpenGApps API, fallbacking to SourceForge RSS...")
- res = requests.get(
- f'https://sourceforge.net/projects/opengapps/rss?path=/{abi_map[arch]}&limit=100')
- link = re.search(f'https://.*{abi_map[arch]}/.*{release}.*{variant}.*\.zip/download', res.text).group().replace(
- '.zip/download', '.zip').replace('sourceforge.net/projects/opengapps/files', 'downloads.sourceforge.net/project/opengapps')
-print(f"download link: {link}", flush=True)
+class BearerAuth(requests.auth.AuthBase):
+ def __init__(self, token):
+ self.token = token
+
+ def __call__(self, r):
+ r.headers["authorization"] = "Bearer " + self.token
+ return r
-with open(download_dir/tempScript, 'a') as f:
- f.writelines(f'{link}\n')
- f.writelines(f' dir={download_dir}\n')
- f.writelines(f' out=OpenGApps-{arch}-{variant}.zip\n')
- f.close
+
+github_auth = None
+if Path.cwd().joinpath('token').exists():
+ with open(Path.cwd().joinpath('token'), 'r') as token_file:
+ github_auth = BearerAuth(token_file.read())
+ print("Using token file for authentication", flush=True)
+arch = sys.argv[1]
+arg2 = sys.argv[2]
+download_dir = Path.cwd().parent / "download" if arg2 == "" else Path(arg2)
+tempScript = sys.argv[3]
+android_api = sys.argv[4]
+file_name = sys.argv[5]
+print(f"Generating GApps download link: arch={arch}", flush=True)
+abi_map = {"x64": "x86_64", "arm64": "arm64"}
+android_api_map = {"30": "11.0", "32": "12.1", "33": "13.0"}
+release = android_api_map[android_api]
+res = requests.get(f"https://api.github.com/repos/LSPosed/WSA-Addon/releases/latest", auth=github_auth)
+json_data = json.loads(res.content)
+headers = res.headers
+x_ratelimit_remaining = headers["x-ratelimit-remaining"]
+if res.status_code == 200:
+ download_files = {}
+ assets = json_data["assets"]
+ for asset in assets:
+ if re.match(rf'gapps.*{release}.*\.rc$', asset["name"]):
+ download_files[asset["name"]] = asset["browser_download_url"]
+ elif re.match(rf'gapps.*{release}.*{abi_map[arch]}.*\.img$', asset["name"]):
+ download_files[asset["name"]] = asset["browser_download_url"]
+ with open(download_dir/tempScript, 'a') as f:
+ for key, value in download_files.items():
+ print(f"download link: {value}\npath: {download_dir / key}\n", flush=True)
+ f.writelines(value + '\n')
+ f.writelines(f' dir={download_dir}\n')
+ f.writelines(f' out={key}\n')
+elif res.status_code == 403 and x_ratelimit_remaining == '0':
+ message = json_data["message"]
+ print(f"Github API Error: {message}", flush=True)
+ ratelimit_reset = headers["x-ratelimit-reset"]
+ ratelimit_reset = datetime.fromtimestamp(int(ratelimit_reset))
+ print(
+ f"The current rate limit window resets in {ratelimit_reset}", flush=True)
+ exit(1)
diff --git a/scripts/generateKernelSULink.py b/scripts/generateKernelSULink.py
new file mode 100644
index 0000000000..5588ea71fd
--- /dev/null
+++ b/scripts/generateKernelSULink.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3
+#
+# This file is part of MagiskOnWSALocal.
+#
+# MagiskOnWSALocal is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# MagiskOnWSALocal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with MagiskOnWSALocal. If not, see .
+#
+# Copyright (C) 2024 LSPosed Contributors
+#
+
+from datetime import datetime
+import sys
+import os
+from typing import Any, OrderedDict
+
+import requests
+import json
+import re
+from pathlib import Path
+from packaging import version
+
+
+class Prop(OrderedDict):
+ def __init__(self, props: str = ...) -> None:
+ super().__init__()
+ for i, line in enumerate(props.splitlines(False)):
+ if '=' in line:
+ k, v = line.split('=', 1)
+ self[k] = v
+ else:
+ self[f".{i}"] = line
+
+ def __setattr__(self, __name: str, __value: Any) -> None:
+ self[__name] = __value
+
+ def __repr__(self):
+ return '\n'.join(f'{item}={self[item]}' for item in self)
+
+
+arch = sys.argv[1]
+arg2 = sys.argv[2]
+download_dir = Path.cwd().parent / "download" if arg2 == "" else Path(arg2)
+tempScript = sys.argv[3]
+kernelVersion = sys.argv[4]
+file_name = sys.argv[5]
+abi_map = {"x64": "x86_64", "arm64": "arm64"}
+print(
+ f"Generating KernelSU download link: arch={abi_map[arch]}, kernel version={kernelVersion}", flush=True)
+res = requests.get(
+ f"https://api.github.com/repos/tiann/KernelSU/releases/latest")
+json_data = json.loads(res.content)
+headers = res.headers
+x_ratelimit_remaining = headers["x-ratelimit-remaining"]
+kernel_ver = 0
+if res.status_code == 200:
+ link = ""
+ assets = json_data["assets"]
+ for asset in assets:
+ asset_name = asset["name"]
+ if re.match(rf'kernel-WSA-{abi_map[arch]}-{kernelVersion}.*\.zip$', asset_name) and asset["content_type"] == "application/zip":
+ tmp_kernel_ver = re.search(
+ u'\d{1}.\d{1,}.\d{1,}.\d{1,}', asset_name.split("-")[3]).group()
+ if (kernel_ver == 0):
+ kernel_ver = tmp_kernel_ver
+ elif version.parse(kernel_ver) < version.parse(tmp_kernel_ver):
+ kernel_ver = tmp_kernel_ver
+ print(f"Kernel version: {kernel_ver}", flush=True)
+ for asset in assets:
+ if re.match(rf'kernel-WSA-{abi_map[arch]}-{kernel_ver}.*\.zip$', asset["name"]) and asset["content_type"] == "application/zip":
+ link = asset["browser_download_url"]
+ break
+ if link == "":
+ print(
+ f"Error: No KernelSU release found for arch={abi_map[arch]}, kernel version={kernelVersion}", flush=True)
+ exit(1)
+ release_name = json_data["name"]
+ with open(os.environ['WSA_WORK_ENV'], 'r') as environ_file:
+ env = Prop(environ_file.read())
+ env.KERNELSU_VER = release_name
+ with open(os.environ['WSA_WORK_ENV'], 'w') as environ_file:
+ environ_file.write(str(env))
+elif res.status_code == 403 and x_ratelimit_remaining == '0':
+ message = json_data["message"]
+ print(f"Github API Error: {message}", flush=True)
+ ratelimit_reset = headers["x-ratelimit-reset"]
+ ratelimit_reset = datetime.fromtimestamp(int(ratelimit_reset))
+ print(
+ f"The current rate limit window resets in {ratelimit_reset}", flush=True)
+ exit(1)
+
+print(f"download link: {link}", flush=True)
+
+with open(download_dir/tempScript, 'a') as f:
+ f.writelines(f'{link}\n')
+ f.writelines(f' dir={download_dir}\n')
+ f.writelines(f' out={file_name}\n')
diff --git a/scripts/generateMagiskLink.py b/scripts/generateMagiskLink.py
index 0578c4be11..29c2d6fe4f 100644
--- a/scripts/generateMagiskLink.py
+++ b/scripts/generateMagiskLink.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#
# This file is part of MagiskOnWSALocal.
#
@@ -15,28 +15,88 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2023 LSPosed Contributors
#
+from datetime import datetime
+import re
import sys
-import os
import json
import requests
from pathlib import Path
+
+class BearerAuth(requests.auth.AuthBase):
+ def __init__(self, token):
+ self.token = token
+
+ def __call__(self, r):
+ r.headers["authorization"] = "Bearer " + self.token
+ return r
+
+
+github_auth = None
+if Path.cwd().joinpath('token').exists():
+ with open(Path.cwd().joinpath('token'), 'r') as token_file:
+ github_auth = BearerAuth(token_file.read())
+ print("Using token file for authentication", flush=True)
+
magisk_ver = sys.argv[1]
-download_dir = Path.cwd().parent / "download" if sys.argv[2] == "" else Path(sys.argv[2]).resolve()
+download_dir = Path.cwd().parent / \
+ "download" if sys.argv[2] == "" else Path(sys.argv[2])
tempScript = sys.argv[3]
-print(f"Generating Magisk download link: release type={magisk_ver}", flush=True)
+download_files = {}
+cdn_hosts=["cdn.jsdelivr.net", "fastly.jsdelivr.net", "testingcf.jsdelivr.net", "gcore.jsdelivr.net"]
+print(
+ f"Generating Magisk download link: release type={magisk_ver}", flush=True)
+magisk_link = None
if not magisk_ver:
magisk_ver = "stable"
if magisk_ver == "stable" or magisk_ver == "beta" or magisk_ver == "canary" or magisk_ver == "debug":
- magisk_link = json.loads(requests.get(
- f"https://github.com/topjohnwu/magisk-files/raw/master/{magisk_ver}.json").content)['magisk']['link']
-print(f"download link: {magisk_link}", flush=True)
+ try:
+ magisk_link = json.loads(requests.get(
+ f"https://topjohnwu.github.io/magisk-files/{magisk_ver}.json").content)['magisk']['link']
+ download_files[f"magisk-{magisk_ver}.zip"] = magisk_link
+ except Exception:
+ print("Failed to fetch from GitHub API, fallbacking to jsdelivr...")
+ for host in cdn_hosts:
+ try:
+ magisk_link = json.loads(requests.get(
+ f"https://{host}/gh/topjohnwu/magisk-files@master/{magisk_ver}.json").content)['magisk']['link']
+ download_files[f"magisk-{magisk_ver}.zip"] = magisk_link
+ break
+ except Exception:
+ print(f"Failed to fetch from {host}, trying next...", flush=True)
+ pass
+ finally:
+ if magisk_link is None:
+ print("Failed to fetch Magisk download link", flush=True)
+ exit(1)
+res = requests.get(
+ f"https://api.github.com/repos/LSPosed/WSA-Addon/releases/latest", auth=github_auth)
+json_data = json.loads(res.content)
+headers = res.headers
+x_ratelimit_remaining = headers["x-ratelimit-remaining"]
+if res.status_code == 200:
+ assets = json_data["assets"]
+ for asset in assets:
+ if re.match(f'cust.img$', asset["name"]):
+ download_files[asset["name"]] = asset["browser_download_url"]
+ break
+elif res.status_code == 403 and x_ratelimit_remaining == '0':
+ message = json_data["message"]
+ print(f"Github API Error: {message}", flush=True)
+ ratelimit_reset = headers["x-ratelimit-reset"]
+ ratelimit_reset = datetime.fromtimestamp(int(ratelimit_reset))
+ print(
+ f"The current rate limit window resets in {ratelimit_reset}", flush=True)
+ exit(1)
with open(download_dir/tempScript, 'a') as f:
- f.writelines(f'{magisk_link}\n')
- f.writelines(f' dir={download_dir}\n')
- f.writelines(f' out=magisk-{magisk_ver}.zip\n')
+ for key, value in download_files.items():
+ print(
+ f"download link: {value}\npath: {download_dir / key}\n", flush=True)
+ f.writelines(value + '\n')
+ f.writelines(f' dir={download_dir}\n')
+ f.writelines(f' out={key}\n')
diff --git a/scripts/generateWSALinks.py b/scripts/generateWSALinks.py
index 95ac2f9556..81781ef585 100644
--- a/scripts/generateWSALinks.py
+++ b/scripts/generateWSALinks.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#
# This file is part of MagiskOnWSALocal.
#
@@ -15,102 +15,178 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2024 LSPosed Contributors
#
-import sys
-
-import requests
-from xml.dom import minidom
import html
-import warnings
+import logging
import re
-import os
+import sys
+
from pathlib import Path
+from threading import Thread
+from typing import Any, OrderedDict
+from xml.dom import minidom
+
+from requests import Session
+from packaging import version
+
-warnings.filterwarnings("ignore")
+class Prop(OrderedDict):
+ def __init__(self, props: str = ...) -> None:
+ super().__init__()
+ for i, line in enumerate(props.splitlines(False)):
+ if '=' in line:
+ k, v = line.split('=', 1)
+ self[k] = v
+ else:
+ self[f".{i}"] = line
+ def __setattr__(self, __name: str, __value: Any) -> None:
+ self[__name] = __value
+
+ def __repr__(self):
+ return '\n'.join(f'{item}={self[item]}' for item in self)
+
+
+logging.captureWarnings(True)
arch = sys.argv[1]
release_name_map = {"retail": "Retail", "RP": "Release Preview",
"WIS": "Insider Slow", "WIF": "Insider Fast"}
release_type = sys.argv[2] if sys.argv[2] != "" else "Retail"
release_name = release_name_map[release_type]
-download_dir = Path.cwd().parent / "download" if sys.argv[3] == "" else Path(sys.argv[3]).resolve()
+download_dir = Path.cwd().parent / \
+ "download" if sys.argv[3] == "" else Path(sys.argv[3])
+ms_account_conf = download_dir/".ms_account"
tempScript = sys.argv[4]
+skip_wsa_download = sys.argv[5] == "1" if len(sys.argv) >= 6 else False
cat_id = '858014f3-3934-4abe-8078-4aa193e74ca8'
-print(f"Generating WSA download link: arch={arch} release_type={release_name}", flush=True)
+user = ''
+session = Session()
+session.verify = False
+if ms_account_conf.is_file():
+ with open(ms_account_conf, "r") as f:
+ conf = Prop(f.read())
+ user = conf.get('user_code')
+print(
+ f"Generating WSA download link: arch={arch} release_type={release_name}\n", flush=True)
with open(Path.cwd().parent / ("xml/GetCookie.xml"), "r") as f:
- cookie_content = f.read()
+ cookie_content = f.read().format(user)
-out = requests.post(
+out = session.post(
'https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx',
data=cookie_content,
- headers={'Content-Type': 'application/soap+xml; charset=utf-8'},
- verify=False
+ headers={'Content-Type': 'application/soap+xml; charset=utf-8'}
)
doc = minidom.parseString(out.text)
cookie = doc.getElementsByTagName('EncryptedData')[0].firstChild.nodeValue
with open(Path.cwd().parent / "xml/WUIDRequest.xml", "r") as f:
- cat_id_content = f.read().format(cookie, cat_id, release_type)
+ cat_id_content = f.read().format(user, cookie, cat_id, release_type)
-out = requests.post(
+out = session.post(
'https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx',
data=cat_id_content,
- headers={'Content-Type': 'application/soap+xml; charset=utf-8'},
- verify=False
+ headers={'Content-Type': 'application/soap+xml; charset=utf-8'}
)
doc = minidom.parseString(html.unescape(out.text))
filenames = {}
-for node in doc.getElementsByTagName('Files'):
- filenames[node.parentNode.parentNode.getElementsByTagName(
- 'ID')[0].firstChild.nodeValue] = f"{node.firstChild.attributes['InstallerSpecificIdentifier'].value}_{node.firstChild.attributes['FileName'].value}"
- pass
-
-identities = []
-for node in doc.getElementsByTagName('SecuredFragment'):
- filename = filenames[node.parentNode.parentNode.parentNode.getElementsByTagName('ID')[
- 0].firstChild.nodeValue]
- update_identity = node.parentNode.parentNode.firstChild
- identities += [(update_identity.attributes['UpdateID'].value,
- update_identity.attributes['RevisionNumber'].value, filename)]
+for node in doc.getElementsByTagName('ExtendedUpdateInfo')[0].getElementsByTagName('Updates')[0].getElementsByTagName('Update'):
+ node_xml = node.getElementsByTagName('Xml')[0]
+ node_files = node_xml.getElementsByTagName('Files')
+ if not node_files:
+ continue
+ else:
+ for node_file in node_files[0].getElementsByTagName('File'):
+ if node_file.hasAttribute('InstallerSpecificIdentifier') and node_file.hasAttribute('FileName'):
+ filenames[node.getElementsByTagName('ID')[0].firstChild.nodeValue] = (f"{node_file.attributes['InstallerSpecificIdentifier'].value}_{node_file.attributes['FileName'].value}",
+ node_xml.getElementsByTagName('ExtendedProperties')[0].attributes['PackageIdentityName'].value)
+
+identities = {}
+for node in doc.getElementsByTagName('NewUpdates')[0].getElementsByTagName('UpdateInfo'):
+ node_xml = node.getElementsByTagName('Xml')[0]
+ if not node_xml.getElementsByTagName('SecuredFragment'):
+ continue
+ else:
+ id = node.getElementsByTagName('ID')[0].firstChild.nodeValue
+ update_identity = node_xml.getElementsByTagName('UpdateIdentity')[0]
+ if id in filenames:
+ fileinfo = filenames[id]
+ if fileinfo[0] not in identities:
+ identities[fileinfo[0]] = ([update_identity.attributes['UpdateID'].value,
+ update_identity.attributes['RevisionNumber'].value], fileinfo[1])
with open(Path.cwd().parent / "xml/FE3FileUrl.xml", "r") as f:
- file_content = f.read()
+ FE3_file_content = f.read()
+
+if not download_dir.is_dir():
+ download_dir.mkdir()
-if not os.path.exists(download_dir):
- os.makedirs(download_dir)
tmpdownlist = open(download_dir/tempScript, 'a')
-for i, v, f in identities:
- if re.match(f"Microsoft\.UI\.Xaml\..*_{arch}_.*\.appx", f):
- out_file_name = f"xaml-{arch}.appx"
- out_file = download_dir / out_file_name
- # elif re.match(f"Microsoft\.VCLibs\..+\.UWPDesktop_.*_{arch}_.*\.appx", f):
- # out_file = download_dir / "vclibs.appx"
- # out_file_name = "vclibs.appx"
- elif re.match(f"MicrosoftCorporationII\.WindowsSubsystemForAndroid_.*\.msixbundle", f):
- out_file_name = f"wsa-{arch}-{release_type}.zip"
- out_file = download_dir / out_file_name
- else:
- continue
- out = requests.post(
+download_files = {}
+
+
+def send_req(i, v, out_file_name):
+ out = session.post(
'https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured',
- data=file_content.format(i, v, release_type),
- headers={'Content-Type': 'application/soap+xml; charset=utf-8'},
- verify=False
+ data=FE3_file_content.format(user, i, v, release_type),
+ headers={'Content-Type': 'application/soap+xml; charset=utf-8'}
)
doc = minidom.parseString(out.text)
for l in doc.getElementsByTagName("FileLocation"):
url = l.getElementsByTagName("Url")[0].firstChild.nodeValue
if len(url) != 99:
- print(f"download link: {url} to {out_file}", flush=True)
- tmpdownlist.writelines(url + '\n')
- tmpdownlist.writelines(f' dir={download_dir}\n')
- tmpdownlist.writelines(f' out={out_file_name}\n')
-tmpdownlist.writelines(f'https://aka.ms/Microsoft.VCLibs.{arch}.14.00.Desktop.appx\n')
-tmpdownlist.writelines(f' dir={download_dir}\n')
-tmpdownlist.writelines(f' out=vclibs-{arch}.appx\n')
-tmpdownlist.close
+ download_files[out_file_name] = url
+
+
+threads = []
+wsa_build_ver = 0
+for filename, values in identities.items():
+ if re.match(rf"MicrosoftCorporationII\.WindowsSubsystemForAndroid_.*\.msixbundle", filename):
+ tmp_wsa_build_ver = re.search(
+ r'\d{4}.\d{5}.\d{1,}.\d{1,}', filename).group()
+ if (wsa_build_ver == 0):
+ wsa_build_ver = tmp_wsa_build_ver
+ elif version.parse(wsa_build_ver) < version.parse(tmp_wsa_build_ver):
+ wsa_build_ver = tmp_wsa_build_ver
+for filename, values in identities.items():
+ if re.match(rf"Microsoft\.UI\.Xaml\..*_{arch}_.*\.appx", filename):
+ out_file_name = f"{values[1]}_{arch}.appx"
+ out_file = download_dir / out_file_name
+ elif re.match(rf"Microsoft\.VCLibs\..+\.UWPDesktop_.*_{arch}_.*\.appx", filename):
+ out_file_name = f"{values[1]}_{arch}.appx"
+ out_file = download_dir / out_file_name
+ elif re.match(rf"Microsoft\.VCLibs\..+_.*_{arch}_.*\.appx", filename):
+ out_file_name = f"{values[1]}_{arch}.appx"
+ out_file = download_dir / out_file_name
+ elif not skip_wsa_download and re.match(rf"MicrosoftCorporationII\.WindowsSubsystemForAndroid_.*\.msixbundle", filename):
+ tmp_wsa_build_ver = re.search(
+ r'\d{4}.\d{5}.\d{1,}.\d{1,}', filename).group()
+ if (wsa_build_ver != tmp_wsa_build_ver):
+ continue
+ version_splitted = wsa_build_ver.split(".")
+ major_ver = version_splitted[0]
+ minor_ver = version_splitted[1]
+ build_ver = version_splitted[2]
+ revision_ver = version_splitted[3]
+ out_file_name = f"wsa-{release_type}.zip"
+ out_file = download_dir / out_file_name
+ else:
+ continue
+ th = Thread(target=send_req, args=(
+ values[0][0], values[0][1], out_file_name))
+ threads.append(th)
+ th.daemon = True
+ th.start()
+for th in threads:
+ th.join()
+print(f'WSA Build Version={wsa_build_ver}\n', flush=True)
+for key, value in download_files.items():
+ print(f"download link: {value}\npath: {download_dir / key}\n", flush=True)
+ tmpdownlist.writelines(value + '\n')
+ tmpdownlist.writelines(f' dir={download_dir}\n')
+ tmpdownlist.writelines(f' out={key}\n')
+tmpdownlist.close()
diff --git a/scripts/init.lsp.magisk.rc b/scripts/init.lsp.magisk.rc
new file mode 100644
index 0000000000..444331ef60
--- /dev/null
+++ b/scripts/init.lsp.magisk.rc
@@ -0,0 +1,2 @@
+on post-fs-data
+ exec u:r:magisk:s0 0 0 -- /system/bin/sh ${MAGISKTMP}/post-fs-data.sh
diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh
new file mode 100755
index 0000000000..5366bc4df0
--- /dev/null
+++ b/scripts/install_deps.sh
@@ -0,0 +1,195 @@
+#!/bin/bash
+#
+# This file is part of MagiskOnWSALocal.
+#
+# MagiskOnWSALocal is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# MagiskOnWSALocal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with MagiskOnWSALocal. If not, see .
+#
+# Copyright (C) 2023 LSPosed Contributors
+#
+
+if [ ! "$BASH_VERSION" ]; then
+ echo "Please do not use sh to run this script, just execute it directly" 1>&2
+ exit 1
+fi
+cd "$(dirname "$0")" || exit 1
+abort() {
+ [ "$1" ] && echo "ERROR: $1"
+ echo "Dependencies: an error has occurred, exit"
+ exit 1
+}
+require_su() {
+ if test "$(id -u)" != "0"; then
+ if [ "$(sudo id -u)" != "0" ]; then
+ echo "sudo is required to run this script"
+ abort
+ fi
+ fi
+}
+
+echo "Checking and ensuring dependencies"
+check_dependencies() {
+ command -v whiptail >/dev/null 2>&1 || command -v dialog >/dev/null 2>&1 || NEED_INSTALL+=("whiptail")
+ command -v pip >/dev/null 2>&1 || NEED_INSTALL+=("python3-pip")
+ command -v aria2c >/dev/null 2>&1 || NEED_INSTALL+=("aria2")
+ command -v 7z >/dev/null 2>&1 || NEED_INSTALL+=("p7zip-full")
+ command -v unzip >/dev/null 2>&1 || NEED_INSTALL+=("unzip")
+}
+check_dependencies
+osrel=$(sed -n '/^ID_LIKE=/s/^.*=//p' /etc/os-release)
+declare -A os_pm_install
+# os_pm_install["/etc/redhat-release"]=yum
+os_pm_install["/etc/arch-release"]=pacman
+os_pm_install["/etc/gentoo-release"]=emerge
+os_pm_install["/etc/SuSE-release"]=zypper
+os_pm_install["/etc/debian_version"]=apt-get
+# os_pm_install["/etc/alpine-release"]=apk
+
+declare -A PM_UPDATE_MAP
+PM_UPDATE_MAP["yum"]="check-update"
+PM_UPDATE_MAP["pacman"]="-Syu --noconfirm"
+PM_UPDATE_MAP["emerge"]="-auDU1 @world"
+PM_UPDATE_MAP["zypper"]="ref"
+PM_UPDATE_MAP["apt-get"]="update"
+PM_UPDATE_MAP["apk"]="update"
+
+declare -A PM_INSTALL_MAP
+PM_INSTALL_MAP["yum"]="install -y"
+PM_INSTALL_MAP["pacman"]="-S --noconfirm --needed"
+PM_INSTALL_MAP["emerge"]="-a"
+PM_INSTALL_MAP["zypper"]="in -y"
+PM_INSTALL_MAP["apt-get"]="install -y"
+PM_INSTALL_MAP["apk"]="add"
+
+declare -A PM_UPGRADE_MAP
+PM_UPGRADE_MAP["apt-get"]="upgrade -y"
+PM_UPGRADE_MAP["zypper"]="up -y"
+
+check_package_manager() {
+ for f in "${!os_pm_install[@]}"; do
+ if [[ -f $f ]]; then
+ PM="${os_pm_install[$f]}"
+ break
+ fi
+ done
+ if [[ "$osrel" = *"suse"* ]]; then
+ PM="zypper"
+ fi
+ if [ -n "$PM" ]; then
+ readarray -td ' ' UPDATE_OPTION <<<"${PM_UPDATE_MAP[$PM]} "
+ unset 'UPDATE_OPTION[-1]'
+ readarray -td ' ' INSTALL_OPTION <<<"${PM_INSTALL_MAP[$PM]} "
+ unset 'INSTALL_OPTION[-1]'
+ readarray -td ' ' UPGRADE_OPTION <<<"${PM_UPGRADE_MAP[$PM]} "
+ unset 'UPGRADE_OPTION[-1]'
+ fi
+}
+
+check_package_manager
+require_su
+if [ -z "$PM" ]; then
+ echo "Unable to determine package manager: Unsupported distros"
+ abort
+elif [[ "$PM" =~ pacman|emerge ]]; then
+ [ "$PM" = "emerge" ] && (sudo emerge -qoO aria2[adns] || abort)
+ i=30
+ while ((i-- > 1)) &&
+ ! read -r -sn 1 -t 1 -p $'\r:: Proceed with full system upgrade? Cancel after '$i$'s.. [y/N]\e[0K ' answer; do
+ :
+ done
+ [[ $answer == [yY] ]] && answer=Yes || answer=No
+ echo "$answer"
+ case "$answer" in
+ Yes)
+ if ! (sudo "$PM" "${UPDATE_OPTION[@]}" ca-certificates); then abort; fi
+ ;;
+ *)
+ abort "Operation cancelled by user"
+ ;;
+ esac
+else
+ if ! (sudo "$PM" "${UPDATE_OPTION[@]}" && sudo "$PM" "${UPGRADE_OPTION[@]}" ca-certificates); then abort; fi
+fi
+
+if [ -n "${NEED_INSTALL[*]}" ]; then
+ if [ "$PM" = "zypper" ]; then
+ NEED_INSTALL_FIX=${NEED_INSTALL[*]}
+ {
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//whiptail/dialog} 2>&1
+ } >>/dev/null
+
+ readarray -td ' ' NEED_INSTALL <<<"$NEED_INSTALL_FIX "
+ unset 'NEED_INSTALL[-1]'
+ elif [ "$PM" = "apk" ]; then
+ NEED_INSTALL_FIX=${NEED_INSTALL[*]}
+ readarray -td ' ' NEED_INSTALL <<<"${NEED_INSTALL_FIX//p7zip-full/p7zip} "
+ unset 'NEED_INSTALL[-1]'
+ elif [ "$PM" = "pacman" ]; then
+ NEED_INSTALL_FIX=${NEED_INSTALL[*]}
+ {
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//whiptail/libnewt} 2>&1
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//python3-pip/python-pip} 2>&1
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//p7zip-full/p7zip} 2>&1
+ } >>/dev/null
+
+ readarray -td ' ' NEED_INSTALL <<<"$NEED_INSTALL_FIX "
+ unset 'NEED_INSTALL[-1]'
+ elif [ "$PM" = "emerge" ]; then
+ NEED_INSTALL_FIX=${NEED_INSTALL[*]}
+ {
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//whiptail/dialog} 2>&1
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//python3-pip/dev-python/pip} 2>&1
+ NEED_INSTALL_FIX=${NEED_INSTALL_FIX//p7zip-full/p7zip} 2>&1
+ } >>/dev/null
+
+ readarray -td ' ' NEED_INSTALL <<<"$NEED_INSTALL_FIX "
+ unset 'NEED_INSTALL[-1]'
+ fi
+ if ! (sudo "$PM" "${INSTALL_OPTION[@]}" "${NEED_INSTALL[@]}"); then abort; fi
+
+fi
+
+python_version=$(python3 -c 'import sys;print("{0}{1}".format(*(sys.version_info[:2])))')
+PYTHON_VENV_DIR="$(dirname "$PWD")/python3-env"
+if [ "$python_version" -ge 311 ] || [ -f "$PYTHON_VENV_DIR/bin/activate" ]; then
+ if ! (python3 -c "import venv" >/dev/null 2>&1) || ! (python3 -c "import ensurepip" >/dev/null 2>&1); then
+ case "$PM" in
+ zypper)
+ if ! (sudo "$PM" "${INSTALL_OPTION[@]}" "python3-venvctrl"); then
+ abort
+ fi
+ ;;
+ *)
+ if ! (sudo "$PM" "${INSTALL_OPTION[@]}" "python3-venv"); then
+ abort
+ fi
+ ;;
+ esac
+ fi
+ echo "Creating python3 virtual env"
+ python3 -m venv --system-site-packages "$PYTHON_VENV_DIR" || {
+ echo "Failed to upgrade python3 virtual env, clear and recreate"
+ python3 -m venv --clear --system-site-packages "$PYTHON_VENV_DIR" || abort "Failed to create python3 virtual env"
+ }
+fi
+if [ -f "$PYTHON_VENV_DIR/bin/activate" ]; then
+ # shellcheck disable=SC1091
+ source "$PYTHON_VENV_DIR"/bin/activate || abort "Failed to activate python3 virtual env"
+ python3 -c "import pkg_resources; pkg_resources.require(open('requirements.txt',mode='r'))" &>/dev/null || {
+ echo "Installing Python3 dependencies"
+ python3 -m pip install -r requirements.txt || abort "Failed to install python3 dependencies"
+ }
+ deactivate
+else
+ python3 -m pip install -r requirements.txt -q || abort "Failed to install python3 dependencies"
+fi
diff --git a/scripts/magisk_debug.sh b/scripts/magisk_debug.sh
new file mode 100644
index 0000000000..2332d8776e
--- /dev/null
+++ b/scripts/magisk_debug.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+#
+# This file is part of MagiskOnWSALocal.
+#
+# MagiskOnWSALocal is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# MagiskOnWSALocal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with MagiskOnWSALocal. If not, see .
+#
+# Copyright (C) 2024 LSPosed Contributors
+#
+
+if [ ! "$BASH_VERSION" ]; then
+ echo "Please do not use sh to run this script, just execute it directly" 1>&2
+ exit 1
+fi
+HOST_ARCH=$(uname -m)
+if [ "$HOST_ARCH" != "x86_64" ] && [ "$HOST_ARCH" != "aarch64" ]; then
+ echo "Unsupported architectures: $HOST_ARCH"
+ exit 1
+fi
+cd "$(dirname "$0")" || exit 1
+# export TMPDIR=$HOME/.cache/wsa
+if [ "$TMPDIR" ] && [ ! -d "$TMPDIR" ]; then
+ mkdir -p "$TMPDIR"
+fi
+WORK_DIR=$(mktemp -d -t wsa-build-XXXXXXXXXX_) || exit 1
+
+DOWNLOAD_DIR=../download
+PYTHON_VENV_DIR="$(dirname "$PWD")/python3-env"
+dir_clean() {
+ rm -rf "${WORK_DIR:?}"
+ if [ "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
+ echo "Cleanup Temp Directory"
+ rm -rf "${TMPDIR:?}"
+ unset TMPDIR
+ fi
+ if [ "$(python3 -c 'import sys ; print( 1 if sys.prefix != sys.base_prefix else 0 )')" = "1" ]; then
+ echo "deactivate python3 venv"
+ deactivate
+ fi
+}
+trap dir_clean EXIT
+abort() {
+ [ "$1" ] && echo -e "ERROR: $1"
+ echo "Build: an error has occurred, exit"
+ if [ -d "$WORK_DIR" ]; then
+ echo -e "\nCleanup Work Directory"
+ dir_clean
+ fi
+ exit 1
+}
+trap abort INT TERM
+# shellcheck disable=SC1091
+[ -f "$PYTHON_VENV_DIR/bin/activate" ] && {
+ source "$PYTHON_VENV_DIR/bin/activate" || abort "Failed to activate virtual environment, please re-run install_deps.sh"
+}
+MAGISK_VER=$1
+ARCH=$2
+TARGET=$3
+if [ -z "$MAGISK_VER" ] || [ -z "$ARCH" ] || [ -z "$TARGET" ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+MAGISK_ZIP=magisk-$MAGISK_VER.zip
+MAGISK_PATH=$DOWNLOAD_DIR/$MAGISK_ZIP
+if [ ! -f "$MAGISK_PATH" ]; then
+ echo "Custom Magisk $MAGISK_ZIP not found"
+ MAGISK_ZIP=app-$MAGISK_VER.apk
+ echo -e "Fallback to $MAGISK_ZIP\n"
+ MAGISK_PATH=$DOWNLOAD_DIR/$MAGISK_ZIP
+ if [ ! -f "$MAGISK_PATH" ]; then
+ abort "Custom Magisk $MAGISK_ZIP not found\nPlease put custom Magisk in $DOWNLOAD_DIR"
+ fi
+fi
+echo "Extracting Magisk"
+if [ -f "$MAGISK_PATH" ]; then
+ if ! python3 extractMagisk.py "$ARCH" "$MAGISK_PATH" "$WORK_DIR"; then
+ abort "Unzip Magisk failed, is the download incomplete?"
+ fi
+ chmod +x "$WORK_DIR/magisk/magiskboot" || abort
+elif [ -z "${CUSTOM_MAGISK+x}" ]; then
+ abort "The Magisk zip package does not exist, is the download incomplete?"
+else
+ abort "The Magisk zip package does not exist, rename it to magisk-debug.zip and put it in the download folder."
+fi
+echo -e "done\n"
+echo "Integrating Magisk"
+SKIP="#"
+SINGLEABI="#"
+SKIPINITLD="#"
+if [ -f "$WORK_DIR/magisk/magisk64" ]; then
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$WORK_DIR/magisk/magisk64" "$WORK_DIR/magisk/magisk64.xz"
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$WORK_DIR/magisk/magisk32" "$WORK_DIR/magisk/magisk32.xz"
+ unset SINGLEABI
+else
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$WORK_DIR/magisk/magisk" "$WORK_DIR/magisk/magisk.xz"
+ unset SKIP
+fi
+if [ -f "$WORK_DIR/magisk/init-ld" ]; then
+ "$WORK_DIR/magisk/magiskboot" compress=xz "$WORK_DIR/magisk/init-ld" "$WORK_DIR/magisk/init-ld.xz"
+ unset SKIPINITLD
+fi
+"$WORK_DIR/magisk/magiskboot" compress=xz "$MAGISK_PATH" "$WORK_DIR/magisk/stub.xz"
+"$WORK_DIR/magisk/magiskboot" cpio "$TARGET" \
+ "add 0750 /lspinit ../bin/$ARCH/lspinit" \
+ "add 0750 /magiskinit $WORK_DIR/magisk/magiskinit" \
+ "$SINGLEABI add 0644 overlay.d/sbin/magisk64.xz $WORK_DIR/magisk/magisk64.xz" \
+ "$SINGLEABI add 0644 overlay.d/sbin/magisk32.xz $WORK_DIR/magisk/magisk32.xz" \
+ "$SKIP add 0644 overlay.d/sbin/magisk.xz $WORK_DIR/magisk/magisk.xz" \
+ "$SKIPINITLD add 0644 overlay.d/sbin/init-ld.xz $WORK_DIR/magisk/init-ld.xz" \
+ "add 0644 overlay.d/sbin/stub.xz $WORK_DIR/magisk/stub.xz" \
+ || abort "Unable to patch initrd"
diff --git a/scripts/post-fs-data.sh b/scripts/post-fs-data.sh
new file mode 100644
index 0000000000..6607569ade
--- /dev/null
+++ b/scripts/post-fs-data.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+MAGISKTMP=/sbin
+[ -d /sbin ] || MAGISKTMP=/debug_ramdisk
+MAGISKBIN=/data/adb/magisk
+if [ ! -d /data/adb ]; then
+ mkdir -m 700 /data/adb
+ chcon u:object_r:adb_data_file:s0 /data/adb
+fi
+if [ ! -d $MAGISKBIN ]; then
+ # shellcheck disable=SC2174
+ mkdir -p -m 755 $MAGISKBIN
+ chcon u:object_r:system_file:s0 $MAGISKBIN
+fi
+ABI=$(getprop ro.product.cpu.abi)
+for file in busybox magiskpolicy magiskboot magiskinit; do
+ [ -x "$MAGISKBIN/$file" ] || {
+ unzip -d $MAGISKBIN -oj $MAGISKTMP/stub.apk "lib/$ABI/lib$file.so"
+ mv $MAGISKBIN/lib$file.so $MAGISKBIN/$file
+ chmod 755 "$MAGISKBIN/$file"
+ }
+done
+for file in util_functions.sh boot_patch.sh; do
+ [ -x "$MAGISKBIN/$file" ] || {
+ unzip -d $MAGISKBIN -oj $MAGISKTMP/stub.apk "assets/$file"
+ chmod 755 "$MAGISKBIN/$file"
+ }
+done
+for file in "$MAGISKTMP"/*; do
+ if echo "$file" | grep -Eq "lsp_.+\.img"; then
+ foldername=$(basename "$file" .img)
+ mkdir -p "$MAGISKTMP/$foldername"
+ mount -t auto -o ro,loop "$file" "$MAGISKTMP/$foldername"
+ "$MAGISKTMP/$foldername/post-fs-data.sh" &
+ fi
+done
+wait
+for file in "$MAGISKTMP"/*; do
+ if echo "$file" | grep -Eq "lsp_.+\.img"; then
+ foldername=$(basename "$file" .img)
+ umount "$MAGISKTMP/$foldername"
+ rm -rf "${MAGISKTMP:?}/${foldername:?}"
+ rm -f "$file"
+ fi
+done
diff --git a/scripts/requirements.txt b/scripts/requirements.txt
new file mode 100644
index 0000000000..64e6ca448f
--- /dev/null
+++ b/scripts/requirements.txt
@@ -0,0 +1,2 @@
+requests
+packaging
diff --git a/scripts/run.sh b/scripts/run.sh
index 1be6535d4b..1756c2370d 100755
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -15,107 +15,55 @@
# You should have received a copy of the GNU Affero General Public License
# along with MagiskOnWSALocal. If not, see .
#
-# Copyright (C) 2022 LSPosed Contributors
+# Copyright (C) 2024 LSPosed Contributors
#
-# DEBUG=--debug
-# CUSTOM_MAGISK=--magisk-custom
-
-DOWNLOAD_DIR=../download
-
if [ ! "$BASH_VERSION" ]; then
echo "Please do not use sh to run this script, just execute it directly" 1>&2
exit 1
fi
cd "$(dirname "$0")" || exit 1
-abort() {
- echo "Dependencies: an error has occurred, exit"
- exit 1
-}
-
-echo "Checking and ensuring dependencies"
-check_dependencies() {
- command -v whiptail >/dev/null 2>&1 || NEED_INSTALL+=("whiptail")
- command -v seinfo >/dev/null 2>&1 || NEED_INSTALL+=("setools")
- command -v lzip >/dev/null 2>&1 || NEED_INSTALL+=("lzip")
- command -v wine64 >/dev/null 2>&1 || NEED_INSTALL+=("wine")
- command -v winetricks >/dev/null 2>&1 || NEED_INSTALL+=("winetricks")
- command -v patchelf >/dev/null 2>&1 || NEED_INSTALL+=("patchelf")
- command -v resize2fs >/dev/null 2>&1 || NEED_INSTALL+=("e2fsprogs")
- command -v pip >/dev/null 2>&1 || NEED_INSTALL+=("python3-pip")
- command -v aria2c >/dev/null 2>&1 || NEED_INSTALL+=("aria2")
-}
-check_dependencies
-declare -A os_pm_install;
-# os_pm_install["/etc/redhat-release"]=yum
-# os_pm_install["/etc/arch-release"]=pacman
-# os_pm_install["/etc/gentoo-release"]=emerge
-# os_pm_install["/etc/SuSE-release"]=zypp
-os_pm_install["/etc/debian_version"]=apt-get
-# os_pm_install["/etc/alpine-release"]=apk
-
-declare -A PM_UPDATE_MAP;
-PM_UPDATE_MAP["yum"]="check-update"
-PM_UPDATE_MAP["pacman"]="-Syu --noconfirm"
-PM_UPDATE_MAP["emerge"]="-auDN @world"
-PM_UPDATE_MAP["zypp"]="update -y"
-PM_UPDATE_MAP["apt-get"]="update"
-PM_UPDATE_MAP["apk"]="update"
-
-declare -A PM_INSTALL_MAP;
-PM_INSTALL_MAP["yum"]="install -y"
-PM_INSTALL_MAP["pacman"]="-S --noconfirm --needed"
-PM_INSTALL_MAP["emerge"]="-a"
-PM_INSTALL_MAP["zypp"]="install -y"
-PM_INSTALL_MAP["apt-get"]="install -y"
-PM_INSTALL_MAP["apk"]="add"
-
-check_package_manager() {
- for f in "${!os_pm_install[@]}"; do
- if [[ -f $f ]]; then
- PM="${os_pm_install[$f]}"
- readarray -td ' ' UPDATE_OPTION <<<"${PM_UPDATE_MAP[$PM]} "; unset 'UPDATE_OPTION[-1]';
- readarray -td ' ' INSTALL_OPTION <<<"${PM_INSTALL_MAP[$PM]} "; unset 'INSTALL_OPTION[-1]';
- break
- fi
- done
-}
-
-check_package_manager
-if [ -n "${NEED_INSTALL[*]}" ]; then
- if [ -z "$PM" ]; then
- echo "Unable to determine package manager: unknown distribution"
- exit 1
- else
- if ! sudo "$PM" "${UPDATE_OPTION[@]}" && sudo "$PM" "${INSTALL_OPTION[@]}" "${NEED_INSTALL[@]}"; then abort; fi
- fi
-fi
-pip list --disable-pip-version-check | grep -E "^requests " >/dev/null 2>&1 || python3 -m pip install requests
-
-winetricks list-installed | grep -E "^msxml6" >/dev/null 2>&1 || {
- cp -r ../wine/.cache/* ~/.cache
- winetricks -q msxml6 || abort
-}
+./install_deps.sh || exit 1
+WHIPTAIL=$(command -v whiptail 2>/dev/null)
+DIALOG=$(command -v dialog 2>/dev/null)
+DIALOG=${WHIPTAIL:-$DIALOG}
function Radiolist {
declare -A o="$1"
shift
- if ! whiptail --nocancel --radiolist "${o[title]}" 0 0 0 "$@" 3>&1 1>&2 2>&3; then
+ if ! $DIALOG --nocancel --radiolist "${o[title]}" 0 0 0 "$@" 3>&1 1>&2 2>&3; then
echo "${o[default]}"
fi
}
function YesNoBox {
+ declare -A o="$1"
+ local default
+ [ "$2" ] && {
+ [ "$2" = "no" ] && default="--defaultno"
+ }
+ shift
+ $DIALOG --title "${o[title]}" $default --yesno "${o[text]}" 0 0
+}
+
+function DialogBox {
declare -A o="$1"
shift
- whiptail --title "${o[title]}" --yesno "${o[text]}" 0 0
+ $DIALOG --title "${o[title]}" --msgbox "${o[text]}" 0 0
}
+intro="Welcome to MagiskOnWSA!
+
+ With this utility, you can integrate Magisk for WSA easily.
+ Use arrow keys to navigate, and press space to select.
+ Press enter to confirm.
+"
+DialogBox "([title]='Intro to MagiskOnWSA' \
+ [text]='$intro')"
ARCH=$(
Radiolist '([title]="Build arch"
[default]="x64")' \
- \
'x64' "X86_64" 'on' \
'arm64' "AArch64" 'off'
)
@@ -123,94 +71,55 @@ ARCH=$(
RELEASE_TYPE=$(
Radiolist '([title]="WSA release type"
[default]="retail")' \
- \
'retail' "Stable Channel" 'on' \
'release preview' "Release Preview Channel" 'off' \
'insider slow' "Beta Channel" 'off' \
'insider fast' "Dev Channel" 'off'
)
+declare -A RELEASE_TYPE_MAP=(["retail"]="retail" ["release preview"]="RP" ["insider slow"]="WIS" ["insider fast"]="WIF")
+COMMAND_LINE=(--arch "$ARCH" --release-type "${RELEASE_TYPE_MAP[$RELEASE_TYPE]}")
+if (YesNoBox '([title]="Root" [text]="Do you want to Root WSA?")'); then
+ ROOT_SOL=$(
+ Radiolist '([title]="Root solution"
+ [default]="magisk")' \
+ 'magisk' "Magisk" 'on' \
+ 'kernelsu' "KernelSU" 'off'
+ )
+ COMMAND_LINE+=(--root-sol "$ROOT_SOL")
+else
+ COMMAND_LINE+=(--root-sol "none")
+fi
-if [ -z "${CUSTOM_MAGISK+x}" ]; then
+if [ "$ROOT_SOL" = "magisk" ]; then
MAGISK_VER=$(
Radiolist '([title]="Magisk version"
- [default]="stable")' \
- \
+ [default]="stable")' \
'stable' "Stable Channel" 'on' \
'beta' "Beta Channel" 'off' \
'canary' "Canary Channel" 'off' \
'debug' "Canary Channel Debug Build" 'off'
)
-else
- MAGISK_VER=debug
-fi
-
-if (YesNoBox '([title]="Install GApps" [text]="Do you want to install GApps?")'); then
- if [ -f "$DOWNLOAD_DIR"/MindTheGapps-"$ARCH".zip ]; then
- GAPPS_BRAND=$(
- Radiolist '([title]="Which GApps do you want to install?"
- [default]="OpenGApps")' \
- \
- 'OpenGApps' "" 'on' \
- 'MindTheGapps' "" 'off'
- )
- else
- GAPPS_BRAND="OpenGApps"
+ COMMAND_LINE+=(--magisk-ver "$MAGISK_VER")
+ if (YesNoBox '([title]="Install GApps" [text]="Do you want to install GApps?")'); then
+ COMMAND_LINE+=(--install-gapps)
fi
-else
- GAPPS_BRAND="none"
-fi
-if [ $GAPPS_BRAND = "OpenGApps" ]; then
- # TODO: Keep it pico since other variants of opengapps are unable to boot successfully
- if [ "$DEBUG" = "1" ]; then
- GAPPS_VARIANT=$(
- Radiolist '([title]="Variants of GApps"
- [default]="pico")' \
- \
- 'super' "" 'off' \
- 'stock' "" 'off' \
- 'full' "" 'off' \
- 'mini' "" 'off' \
- 'micro' "" 'off' \
- 'nano' "" 'off' \
- 'pico' "" 'on' \
- 'tvstock' "" 'off' \
- 'tvmini' "" 'off'
- )
- else
- GAPPS_VARIANT=pico
- fi
-else
- GAPPS_VARIANT="pico"
fi
-if (YesNoBox '([title]="Remove Amazon Appstore" [text]="Do you want to keep Amazon Appstore?")'); then
- REMOVE_AMAZON=""
-else
- REMOVE_AMAZON="--remove-amazon"
+if (YesNoBox '([title]="Remove Amazon Appstore" [text]="Do you want to remove Amazon Appstore?")' no); then
+ COMMAND_LINE+=(--remove-amazon)
fi
-ROOT_SOL=$(
- Radiolist '([title]="Root solution"
- [default]="magisk")' \
- \
- 'magisk' "" 'on' \
- 'none' "" 'off'
-)
-
if (YesNoBox '([title]="Compress output" [text]="Do you want to compress the output?")'); then
- COMPRESS_OUTPUT="--compress"
-else
- COMPRESS_OUTPUT=""
+ COMPRESS_FORMAT=$(
+ Radiolist '([title]="Compress format"
+ [default]="7z")' \
+ '7z' "7-Zip" 'on' \
+ 'zip' "Zip" 'off'
+ )
+ COMMAND_LINE+=(--compress-format "$COMPRESS_FORMAT")
fi
-# if ! (YesNoBox '([title]="Off line mode" [text]="Do you want to enable off line mode?")'); then
-# OFFLINE="--offline"
-# else
-# OFFLINE=""
-# fi
-# OFFLINE="--offline"
clear
-declare -A RELEASE_TYPE_MAP=(["retail"]="retail" ["release preview"]="RP" ["insider slow"]="WIS" ["insider fast"]="WIF")
-COMMAND_LINE=(--arch "$ARCH" --release-type "${RELEASE_TYPE_MAP[$RELEASE_TYPE]}" --magisk-ver "$MAGISK_VER" --gapps-brand "$GAPPS_BRAND" --gapps-variant "$GAPPS_VARIANT" "$REMOVE_AMAZON" --root-sol "$ROOT_SOL" "$COMPRESS_OUTPUT" "$OFFLINE" "$DEBUG" "$CUSTOM_MAGISK")
echo "COMMAND_LINE=${COMMAND_LINE[*]}"
+chmod +x ./build.sh
./build.sh "${COMMAND_LINE[@]}"
diff --git a/wine/.cache/winetricks/msxml6/msxml6-KB973686-enu-amd64.exe b/wine/.cache/winetricks/msxml6/msxml6-KB973686-enu-amd64.exe
deleted file mode 100755
index 20804d8fde..0000000000
Binary files a/wine/.cache/winetricks/msxml6/msxml6-KB973686-enu-amd64.exe and /dev/null differ
diff --git a/wine/aarch64/makepri.exe b/wine/aarch64/makepri.exe
deleted file mode 100755
index dbde533557..0000000000
Binary files a/wine/aarch64/makepri.exe and /dev/null differ
diff --git a/wine/x86_64/makepri.exe b/wine/x86_64/makepri.exe
deleted file mode 100755
index 0207ba5b07..0000000000
Binary files a/wine/x86_64/makepri.exe and /dev/null differ
diff --git a/x64/gapps/priv-app/SetupWizard/SetupWizard.apk b/x64/gapps/priv-app/SetupWizard/SetupWizard.apk
deleted file mode 100644
index a73639e342..0000000000
Binary files a/x64/gapps/priv-app/SetupWizard/SetupWizard.apk and /dev/null differ
diff --git a/x64/gapps/product/overlay/GoogleWebViewOverlay.apk b/x64/gapps/product/overlay/GoogleWebViewOverlay.apk
deleted file mode 100644
index 44ac318b26..0000000000
Binary files a/x64/gapps/product/overlay/GoogleWebViewOverlay.apk and /dev/null differ
diff --git a/x64/system/system/etc/permissions/android.software.device_admin.xml b/x64/system/system/etc/permissions/android.software.device_admin.xml
deleted file mode 100644
index 7d14dc661c..0000000000
--- a/x64/system/system/etc/permissions/android.software.device_admin.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
diff --git a/x64/system/system/priv-app/VpnDialogs/VpnDialogs.apk b/x64/system/system/priv-app/VpnDialogs/VpnDialogs.apk
deleted file mode 100644
index 4179a48238..0000000000
Binary files a/x64/system/system/priv-app/VpnDialogs/VpnDialogs.apk and /dev/null differ
diff --git a/x64/system/system/priv-app/WSAHelper/WSAHelper.apk b/x64/system/system/priv-app/WSAHelper/WSAHelper.apk
deleted file mode 100755
index 9817e059ca..0000000000
Binary files a/x64/system/system/priv-app/WSAHelper/WSAHelper.apk and /dev/null differ
diff --git a/xml/FE3FileUrl.xml b/xml/FE3FileUrl.xml
index de2e6ad2ec..093c314b52 100644
--- a/xml/FE3FileUrl.xml
+++ b/xml/FE3FileUrl.xml
@@ -1,40 +1,37 @@
-
-
- http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetExtendedUpdateInfo2
- urn:uuid:2cc99c2e-3b3e-4fb1-9e31-0cd30e6f43a0
- https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured
-
+ http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetExtendedUpdateInfo2
+ urn:uuid:2cc99c2e-3b3e-4fb1-9e31-0cd30e6f43a0
+ https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured
+
-
- 2017-08-01T00:29:01.868Z
- 2017-08-01T00:34:01.868Z
-
-
+ 2017-08-01T00:29:01.868Z
+ 2017-08-01T00:34:01.868Z
+
+
-
- dAA9AEUAdwBBAHcAQQBzAE4AMwBCAEEAQQBVADEAYgB5AHMAZQBtAGIAZQBEAFYAQwArADMAZgBtADcAbwBXAHkASAA3AGIAbgBnAEcAWQBtAEEAQQBMAGoAbQBqAFYAVQB2AFEAYwA0AEsAVwBFAC8AYwBDAEwANQBYAGUANABnAHYAWABkAGkAegBHAGwAZABjADEAZAAvAFcAeQAvAHgASgBQAG4AVwBRAGUAYwBtAHYAbwBjAGkAZwA5AGoAZABwAE4AawBIAG0AYQBzAHAAVABKAEwARAArAFAAYwBBAFgAbQAvAFQAcAA3AEgAagBzAEYANAA0AEgAdABsAC8AMQBtAHUAcgAwAFMAdQBtAG8AMABZAGEAdgBqAFIANwArADQAcABoAC8AcwA4ADEANgBFAFkANQBNAFIAbQBnAFIAQwA2ADMAQwBSAEoAQQBVAHYAZgBzADQAaQB2AHgAYwB5AEwAbAA2AHoAOABlAHgAMABrAFgAOQBPAHcAYQB0ADEAdQBwAFMAOAAxAEgANgA4AEEASABzAEoAegBnAFQAQQBMAG8AbgBBADIAWQBBAEEAQQBpAGcANQBJADMAUQAvAFYASABLAHcANABBAEIAcQA5AFMAcQBhADEAQgA4AGsAVQAxAGEAbwBLAEEAdQA0AHYAbABWAG4AdwBWADMAUQB6AHMATgBtAEQAaQBqAGgANQBkAEcAcgBpADgAQQBlAEUARQBWAEcAbQBXAGgASQBCAE0AUAAyAEQAVwA0ADMAZABWAGkARABUAHoAVQB0AHQARQBMAEgAaABSAGYAcgBhAGIAWgBsAHQAQQBUAEUATABmAHMARQBGAFUAYQBRAFMASgB4ADUAeQBRADgAagBaAEUAZQAyAHgANABCADMAMQB2AEIAMgBqAC8AUgBLAGEAWQAvAHEAeQB0AHoANwBUAHYAdAB3AHQAagBzADYAUQBYAEIAZQA4AHMAZwBJAG8AOQBiADUAQQBCADcAOAAxAHMANgAvAGQAUwBFAHgATgBEAEQAYQBRAHoAQQBYAFAAWABCAFkAdQBYAFEARQBzAE8AegA4AHQAcgBpAGUATQBiAEIAZQBUAFkAOQBiAG8AQgBOAE8AaQBVADcATgBSAEYAOQAzAG8AVgArAFYAQQBiAGgAcAAwAHAAUgBQAFMAZQBmAEcARwBPAHEAdwBTAGcANwA3AHMAaAA5AEoASABNAHAARABNAFMAbgBrAHEAcgAyAGYARgBpAEMAUABrAHcAVgBvAHgANgBuAG4AeABGAEQAbwBXAC8AYQAxAHQAYQBaAHcAegB5AGwATABMADEAMgB3AHUAYgBtADUAdQBtAHAAcQB5AFcAYwBLAFIAagB5AGgAMgBKAFQARgBKAFcANQBnAFgARQBJADUAcAA4ADAARwB1ADIAbgB4AEwAUgBOAHcAaQB3AHIANwBXAE0AUgBBAFYASwBGAFcATQBlAFIAegBsADkAVQBxAGcALwBwAFgALwB2AGUATAB3AFMAawAyAFMAUwBIAGYAYQBLADYAagBhAG8AWQB1AG4AUgBHAHIAOABtAGIARQBvAEgAbABGADYASgBDAGEAYQBUAEIAWABCAGMAdgB1AGUAQwBKAG8AOQA4AGgAUgBBAHIARwB3ADQAKwBQAEgAZQBUAGIATgBTAEUAWABYAHoAdgBaADYAdQBXADUARQBBAGYAZABaAG0AUwA4ADgAVgBKAGMAWgBhAEYASwA3AHgAeABnADAAdwBvAG4ANwBoADAAeABDADYAWgBCADAAYwBZAGoATAByAC8ARwBlAE8AegA5AEcANABRAFUASAA5AEUAawB5ADAAZAB5AEYALwByAGUAVQAxAEkAeQBpAGEAcABwAGgATwBQADgAUwAyAHQANABCAHIAUABaAFgAVAB2AEMAMABQADcAegBPACsAZgBHAGsAeABWAG0AKwBVAGYAWgBiAFEANQA1AHMAdwBFAD0AJgBwAD0A
-
-
-
-
-
-
-
-
- {}
- {}
-
-
-
- FileUrl
- FileDecryption
-
- BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.16184.1001;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.16184.1001;DeviceFamily=Windows.Desktop;
-
-
+
+ {}
+
+
+
+
+
+
+
+
+ {}
+ {}
+
+
+
+ FileUrl
+ FileDecryption
+
+ BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.22621.900;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.22621.900;DeviceFamily=Windows.Desktop;
+
+
diff --git a/xml/GetCookie.xml b/xml/GetCookie.xml
index e8de3a56f7..6006128fff 100644
--- a/xml/GetCookie.xml
+++ b/xml/GetCookie.xml
@@ -1,27 +1,37 @@
-
-
- http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie
- urn:uuid:b9b43757-2247-4d7b-ae8f-a71ba8a22386
- https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx
-
-
- 2017-12-02T00:16:15.210Z
- 2017-12-29T06:25:43.943Z
-
-
-
-
-
-
-
-
-
-
-
-
- 2015-10-21T17:01:07.1472913Z
- 2017-12-02T00:16:15.217Z
- 1.40
-
-
+
+
+ http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie
+ urn:uuid:b9b43757-2247-4d7b-ae8f-a71ba8a22386
+ https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx
+
+
+ 2017-12-02T00:16:15.210Z
+ 2017-12-29T06:25:43.943Z
+
+
+
+ {}
+
+
+
+
+
+
+
+
+ 2015-10-21T17:01:07.1472913Z
+ 2017-12-02T00:16:15.217Z
+ 1.40
+
+
\ No newline at end of file
diff --git a/xml/WUIDRequest.xml b/xml/WUIDRequest.xml
index 2a1be9e2a9..4c2a32bf6d 100644
--- a/xml/WUIDRequest.xml
+++ b/xml/WUIDRequest.xml
@@ -1,5 +1,4 @@
-
http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/SyncUpdates
@@ -7,8 +6,7 @@
https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx
-
+
2017-08-05T02:03:05.038Z
2017-08-05T02:08:05.038Z
@@ -16,14 +14,13 @@
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wuws="http://schemas.microsoft.com/msus/2014/10/WindowsUpdateAuthorization">
- dAA9AEUAdwBBAHcAQQBzAE4AMwBCAEEAQQBVADEAYgB5AHMAZQBtAGIAZQBEAFYAQwArADMAZgBtADcAbwBXAHkASAA3AGIAbgBnAEcAWQBtAEEAQQBMAGoAbQBqAFYAVQB2AFEAYwA0AEsAVwBFAC8AYwBDAEwANQBYAGUANABnAHYAWABkAGkAegBHAGwAZABjADEAZAAvAFcAeQAvAHgASgBQAG4AVwBRAGUAYwBtAHYAbwBjAGkAZwA5AGoAZABwAE4AawBIAG0AYQBzAHAAVABKAEwARAArAFAAYwBBAFgAbQAvAFQAcAA3AEgAagBzAEYANAA0AEgAdABsAC8AMQBtAHUAcgAwAFMAdQBtAG8AMABZAGEAdgBqAFIANwArADQAcABoAC8AcwA4ADEANgBFAFkANQBNAFIAbQBnAFIAQwA2ADMAQwBSAEoAQQBVAHYAZgBzADQAaQB2AHgAYwB5AEwAbAA2AHoAOABlAHgAMABrAFgAOQBPAHcAYQB0ADEAdQBwAFMAOAAxAEgANgA4AEEASABzAEoAegBnAFQAQQBMAG8AbgBBADIAWQBBAEEAQQBpAGcANQBJADMAUQAvAFYASABLAHcANABBAEIAcQA5AFMAcQBhADEAQgA4AGsAVQAxAGEAbwBLAEEAdQA0AHYAbABWAG4AdwBWADMAUQB6AHMATgBtAEQAaQBqAGgANQBkAEcAcgBpADgAQQBlAEUARQBWAEcAbQBXAGgASQBCAE0AUAAyAEQAVwA0ADMAZABWAGkARABUAHoAVQB0AHQARQBMAEgAaABSAGYAcgBhAGIAWgBsAHQAQQBUAEUATABmAHMARQBGAFUAYQBRAFMASgB4ADUAeQBRADgAagBaAEUAZQAyAHgANABCADMAMQB2AEIAMgBqAC8AUgBLAGEAWQAvAHEAeQB0AHoANwBUAHYAdAB3AHQAagBzADYAUQBYAEIAZQA4AHMAZwBJAG8AOQBiADUAQQBCADcAOAAxAHMANgAvAGQAUwBFAHgATgBEAEQAYQBRAHoAQQBYAFAAWABCAFkAdQBYAFEARQBzAE8AegA4AHQAcgBpAGUATQBiAEIAZQBUAFkAOQBiAG8AQgBOAE8AaQBVADcATgBSAEYAOQAzAG8AVgArAFYAQQBiAGgAcAAwAHAAUgBQAFMAZQBmAEcARwBPAHEAdwBTAGcANwA3AHMAaAA5AEoASABNAHAARABNAFMAbgBrAHEAcgAyAGYARgBpAEMAUABrAHcAVgBvAHgANgBuAG4AeABGAEQAbwBXAC8AYQAxAHQAYQBaAHcAegB5AGwATABMADEAMgB3AHUAYgBtADUAdQBtAHAAcQB5AFcAYwBLAFIAagB5AGgAMgBKAFQARgBKAFcANQBnAFgARQBJADUAcAA4ADAARwB1ADIAbgB4AEwAUgBOAHcAaQB3AHIANwBXAE0AUgBBAFYASwBGAFcATQBlAFIAegBsADkAVQBxAGcALwBwAFgALwB2AGUATAB3AFMAawAyAFMAUwBIAGYAYQBLADYAagBhAG8AWQB1AG4AUgBHAHIAOABtAGIARQBvAEgAbABGADYASgBDAGEAYQBUAEIAWABCAGMAdgB1AGUAQwBKAG8AOQA4AGgAUgBBAHIARwB3ADQAKwBQAEgAZQBUAGIATgBTAEUAWABYAHoAdgBaADYAdQBXADUARQBBAGYAZABaAG0AUwA4ADgAVgBKAGMAWgBhAEYASwA3AHgAeABnADAAdwBvAG4ANwBoADAAeABDADYAWgBCADAAYwBZAGoATAByAC8ARwBlAE8AegA5AEcANABRAFUASAA5AEUAawB5ADAAZAB5AEYALwByAGUAVQAxAEkAeQBpAGEAcABwAGgATwBQADgAUwAyAHQANABCAHIAUABaAFgAVAB2AEMAMABQADcAegBPACsAZgBHAGsAeABWAG0AKwBVAGYAWgBiAFEANQA1AHMAdwBFAD0AJgBwAD0A
+ {}
-
+
2045-03-11T02:02:48Z
{}
@@ -670,7 +667,7 @@
false
- BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.16184.1001;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.16184.1001;DeviceFamily=Windows.Desktop;
+ BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.22621.900;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.22621.900;DeviceFamily=Windows.Desktop;
Interactive=1;IsSeeker=0;
diff --git a/xml/priconfig.xml b/xml/priconfig.xml
new file mode 100644
index 0000000000..be00740502
--- /dev/null
+++ b/xml/priconfig.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file