# Per-user NTUSER.DAT shell-folder cleanup for ProfWiz-migrated Cascades users.
#
# WHAT IT DOES
#   Finds the user's offline NTUSER.DAT, backs it up, loads the hive, and resets
#   any User Shell Folders values that are poisoned with the SYSTEM-profile path
#   (C:\Windows\system32\config\systemprofile\...) back to the standard
#   %USERPROFILE%\<Folder> REG_EXPAND_SZ defaults. Desktop is intentionally NOT
#   touched — on machines with a working Desktop reg hack, leaving it alone is
#   the safe default.
#
# WHEN TO USE
#   ProfWiz-migrated user whose Folder Redirection GPO won't apply cleanly,
#   whose logon hangs at "Welcome," or whose Documents/Downloads sidebar shows
#   the "this file has no associated app" error. Always verify the hive is
#   poisoned FIRST by logging in and reading HKCU\...\User Shell Folders.
#
# HOW TO RUN
#   - ScreenConnect Backstage PowerShell (runs as SYSTEM) is the most reliable
#   - User MUST be logged OFF (hive loads from NTUSER.DAT on disk; can't be
#     locked by an active session)
#   - Pass the user's profile path as -ProfilePath, or omit to use the default
#     C:\Users\<sam>\
#
# ROLLBACK
#   A timestamped backup is written to C:\ProfileBackups\ before any change.
#   Restore: Copy-Item <backup> <ntuser-path> -Force  (user logged out)

[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string]$ProfilePath,   # e.g. 'C:\Users\Sharon Edwards'

    [string]$BackupDir = 'C:\ProfileBackups',

    [string]$TempHiveName = 'ProfileFix'
)

$ErrorActionPreference = 'Stop'

$ntuser = Join-Path $ProfilePath 'NTUSER.DAT'
if (-not (Test-Path $ntuser)) { throw "NTUSER.DAT not found at $ntuser" }

New-Item -ItemType Directory -Path $BackupDir -Force | Out-Null
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$leaf  = Split-Path $ProfilePath -Leaf
$backup = Join-Path $BackupDir "$leaf-NTUSER.DAT.$stamp.bak"
Copy-Item $ntuser $backup -Force
Write-Host "[OK] Backup -> $backup"

if (Test-Path "Registry::HKEY_USERS\$TempHiveName") {
    reg unload "HKU\$TempHiveName" 2>&1 | Out-Null
    Start-Sleep 1
}
$loadResult = reg load "HKU\$TempHiveName" $ntuser 2>&1
if ($LASTEXITCODE -ne 0) { throw "reg load failed: $loadResult" }
Write-Host "[OK] Hive loaded at HKU\$TempHiveName"

try {
    $USF = "Registry::HKEY_USERS\$TempHiveName\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"

    # Known-poisoned value names + their default REG_EXPAND_SZ targets.
    # Desktop is deliberately omitted — don't clobber working redirections.
    # Include BOTH the legacy names and the KnownFolder GUID forms so the
    # Explorer sidebar resolves to the same place.
    $resets = [ordered]@{
        'Personal'                                = '%USERPROFILE%\Documents'
        'My Music'                                = '%USERPROFILE%\Music'
        'My Pictures'                             = '%USERPROFILE%\Pictures'
        'My Video'                                = '%USERPROFILE%\Videos'
        'Favorites'                               = '%USERPROFILE%\Favorites'
        '{FDD39AD0-238F-46AF-ADB4-6C85480369C7}'  = '%USERPROFILE%\Documents'  # Documents KF
        '{374DE290-123F-4565-9164-39C4925E467B}'  = '%USERPROFILE%\Downloads'  # Downloads KF
    }

    # Only touch a value if it's CURRENTLY poisoned (points under systemprofile)
    # or missing. This keeps working redirections (e.g., UNC paths set by a
    # functioning CSE) intact.
    $poisonPrefix = 'C:\Windows\system32\config\systemprofile'

    foreach ($name in $resets.Keys) {
        $current = (Get-ItemProperty -Path $USF -Name $name -ErrorAction SilentlyContinue).$name
        $new     = $resets[$name]

        if ($null -eq $current) {
            New-ItemProperty -Path $USF -Name $name -Value $new -PropertyType ExpandString -Force | Out-Null
            Write-Host "  [ADDED]   $name = $new"
        } elseif ($current -like "$poisonPrefix*") {
            Set-ItemProperty -Path $USF -Name $name -Value $new -Type ExpandString
            Write-Host "  [CHANGED] $name : '$current' -> '$new' (was poisoned)"
        } else {
            Write-Host "  [KEEP]    $name = '$current' (not poisoned, leaving alone)"
        }
    }
} finally {
    [gc]::Collect()
    Start-Sleep 2
    reg unload "HKU\$TempHiveName" 2>&1 | Out-Null
    Write-Host "[OK] Hive unloaded"
}

Write-Host "`nBackup: $backup"
Write-Host "Rollback: Copy-Item '$backup' '$ntuser' -Force  (while user logged out)"
