fix dll overrides & add disable UMU

This commit is contained in:
olcxja 2026-10-04 15:40:09 +02:00
commit 8c6db38fab
12 changed files with 295 additions and 45 deletions

View file

@ -15,6 +15,7 @@ function seed() {
if (!defs || !Array.isArray(defs.prefixes) || !defs.prefixes.length) {
const seeded = { default: MAIN, prefixes: [{ name: MAIN, created: Date.now(), locked: true }] }
if (!fs.existsSync(prefixPath(MAIN))) fs.mkdirSync(prefixPath(MAIN), { recursive: true })
ensureUnifiedPrefix(MAIN)
writeJson(REGISTRY, seeded)
}
}
@ -42,22 +43,65 @@ function prefixExists(name) {
}
// Every Windows C: drive a prefix has: plain wine keeps one at the top
// (WINEPREFIX=<prefix>), Proton-managed prefixes nest one under pfx/
// (WINEPREFIX=<prefix>/pfx). A prefix used with BOTH wine kinds has both,
// and an import may come from either one - so callers that can accept
// several get them all, top level first.
// (WINEPREFIX=<prefix>), legacy Proton-managed prefixes nest one under pfx/
// (WINEPREFIX=<prefix>/pfx). A prefix used with BOTH wine kinds has both, and
// an import may come from either one - so callers that can accept several get
// them all, top level first. A unified prefix (pfx -> .) reaches the same
// drive twice; it is reported once.
function prefixDriveRoots(name) {
const root = prefixPath(name)
const found = []
const seen = new Set()
for (const base of [root, path.join(root, 'pfx')]) {
try {
const driveC = path.join(base, 'drive_c')
if (fs.statSync(driveC).isDirectory()) found.push(driveC)
if (!fs.statSync(driveC).isDirectory()) continue
const real = fs.realpathSync(driveC)
if (seen.has(real)) continue
seen.add(real)
found.push(driveC)
} catch {}
}
return found
}
function lstatOrNull(p) {
try {
return fs.lstatSync(p)
} catch {
return null
}
}
// Wine keeps its C: drive at <prefix>/drive_c, Proton always runs its prefix
// from <compatdata>/pfx - and PLWL points compatdata at the launcher's prefix
// folder, so without a link a prefix used with both wine kinds grows TWO C:
// drives with separate registries, saves and installed DLLs. Making `pfx` a
// relative symlink back to the prefix itself collapses them: Proton's
// <compatdata>/pfx resolves to the prefix root, the exact folder wine uses.
// Every walker PLWL owns (fsutil, symlinks, LAN sync) treats symlinks as
// links and never follows them, so the self-reference is safe.
//
// Only a prefix that has no pfx AT ALL gets the link - that covers a fresh
// prefix and a plain-wine prefix first used through Proton. An existing
// layout is left exactly as it is: a prefix from an older PLWL keeps its real
// pfx/ folder (and here the two wine kinds keep two C: drives), and a prefix
// with both real drive_c trees keeps them - moving Windows installs around
// behind the user's back loses data and breaks the absolute/relative links
// inside them.
function ensureUnifiedPrefix(name) {
if (!name) return false
const pfx = path.join(prefixPath(name), 'pfx')
if (lstatOrNull(pfx)) return false
try {
fs.symlinkSync('.', pfx, 'dir')
return true
} catch {
// the prefix folder may not exist yet - the link is added on creation
return false
}
}
// True when a path IS one of a prefix's own roots: the prefix folder, its
// pfx/ or either drive_c. A copy/move import of such a folder would move the
// prefix's C: drive (or the whole prefix) into files/apps, gutting it - the
@ -82,6 +126,7 @@ function createPrefix(name) {
if (clean.toLowerCase() === MAIN.toLowerCase()) return { ok: false, error: 'alreadyExists' }
if (fs.existsSync(prefixPath(clean))) return { ok: false, error: 'alreadyExists' }
fs.mkdirSync(prefixPath(clean), { recursive: true })
ensureUnifiedPrefix(clean)
const defs = listPrefixes()
defs.prefixes.push({ name: clean, created: Date.now() })
if (!defs.prefixes.some(p => p.name === defs.default)) defs.default = clean
@ -153,4 +198,4 @@ function setDefaultPrefix(name) {
return { ok: true }
}
module.exports = { listPrefixes, savePrefixes, createPrefix, deletePrefix, renamePrefix, setDefaultPrefix, prefixPath, prefixExists, prefixDriveRoots, isPrefixRoot, healPrefix, MAIN }
module.exports = { listPrefixes, savePrefixes, createPrefix, deletePrefix, renamePrefix, setDefaultPrefix, prefixPath, prefixExists, prefixDriveRoots, isPrefixRoot, healPrefix, ensureUnifiedPrefix, MAIN }