# BSOD (Blue Screen) info collection - Run as Administrator for full access
# Output saved to BSODReport_*.txt in same folder

$ReportDir = $PSScriptRoot
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$ReportFile = Join-Path $ReportDir "BSODReport_$Timestamp.txt"

function Write-Report {
    param([string]$Text, [string]$Section = "")
    if ($Section) { $script:Report += "`n========== $Section ==========`n" }
    $script:Report += $Text + "`n"
}

# Common BugCheck codes (hex, 0x prefix optional)
$BugCheckNames = @{
    "0x0000000A" = "IRQL_NOT_LESS_OR_EQUAL"
    "0x0000001E" = "KMODE_EXCEPTION_NOT_HANDLED"
    "0x0000003B" = "SYSTEM_SERVICE_EXCEPTION"
    "0x00000050" = "PAGE_FAULT_IN_NONPAGED_AREA"
    "0x0000007E" = "SYSTEM_THREAD_EXCEPTION_NOT_HANDLED"
    "0x0000007F" = "UNEXPECTED_KERNEL_MODE_TRAP"
    "0x000000D1" = "DRIVER_IRQL_NOT_LESS_OR_EQUAL"
    "0x000000D8" = "DRIVER_USED_EXCESSIVE_PTES"
    "0x000000EA" = "THREAD_STUCK_IN_DEVICE_DRIVER"
    "0x000000BE" = "ATTEMPTED_WRITE_TO_READONLY_MEMORY"
    "0x000000C2" = "BAD_POOL_CALLER"
    "0x000000C5" = "DRIVER_CORRUPTED_EXPOOL"
    "0x000000EF" = "CRITICAL_PROCESS_DIED"
    "0x00000109" = "CRITICAL_STRUCTURE_CORRUPTION"
    "0x00000133" = "DPC_WATCHDOG_VIOLATION"
    "0x00000139" = "KERNEL_SECURITY_CHECK_FAILURE"
    "0x000001E2" = "KERNEL_MODE_HEAP_CORRUPTION"
    "0x0000014C" = "REFERENCE_BY_POINTER"
    "0x00000019" = "BAD_POOL_HEADER"
    "0x0000001A" = "MEMORY_MANAGEMENT"
}

function Get-BugCheckName {
    param([string]$Code)
    $h = if ($Code -match "^0x") { $Code } else { "0x" + $Code }
    $h = $h.ToUpper()
    if ($BugCheckNames[$h]) { return $BugCheckNames[$h] }
    return $Code
}

$Report = ""
Write-Report "BSOD / Blue Screen Crash Report" "Header"
Write-Report "Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Report "Computer: $env:COMPUTERNAME"
Write-Report "Run this AFTER reboot to collect the previous crash info."

# 1. Event 1001 - Windows Error Reporting (Application log)
Write-Report "" "[Primary] BugCheck / BSOD (Event 1001, Application log)"
try {
    $evt = Get-WinEvent -FilterHashtable @{ LogName = 'Application'; Id = 1001; ProviderName = 'Windows Error Reporting' } -MaxEvents 20 -ErrorAction SilentlyContinue
    if ($evt) {
        foreach ($e in $evt) {
            $msg = $e.Message
            $code = ""
            if ($msg -match "BugcheckCode\s*:\s*(\d+)") { $code = $Matches[1]; $hex = "0x{0:X8}" -f [int]$code; $name = Get-BugCheckName $hex }
            Write-Report "  Time: $($e.TimeCreated)"
            Write-Report "  Message: $($msg.Substring(0, [Math]::Min(500, $msg.Length)))"
            if ($code) { Write-Report "  -> BugCheck: $hex ($name)" }
            Write-Report ""
        }
    } else { Write-Report "  No Event 1001 (WER) records. Try running as Administrator." }
} catch { Write-Report "  Read failed: $($_.Exception.Message)" }

# 2. Kernel-Power Event 41 (includes BugcheckCode when present)
Write-Report "" "[Important] Unclean shutdown (Kernel-Power Event 41)"
try {
    $evt41 = Get-WinEvent -FilterHashtable @{ LogName = 'System'; Id = 41; ProviderName = 'Microsoft-Windows-Kernel-Power' } -MaxEvents 20 -ErrorAction SilentlyContinue
    if ($evt41) {
        foreach ($e in $evt41) {
            Write-Report "  Time: $($e.TimeCreated)"
            if ($e.Properties -and $e.Properties.Count -ge 1 -and $e.Properties[0].Value) {
                $code = $e.Properties[0].Value
                $hex = "0x{0:X8}" -f [int]$code
                $name = Get-BugCheckName $hex
                Write-Report "  BugcheckCode: $hex ($name)"
            }
            Write-Report ""
        }
    } else { Write-Report "  No Event 41 records" }
} catch { Write-Report "  Read failed: $($_.Exception.Message)" }

# 3. Event 6008 - Unexpected shutdown
Write-Report "" "Unexpected shutdown (Event 6008)"
try {
    $evt6008 = Get-WinEvent -FilterHashtable @{ LogName = 'System'; Id = 6008 } -MaxEvents 10 -ErrorAction SilentlyContinue
    if ($evt6008) {
        foreach ($e in $evt6008) {
            Write-Report "  Previous shutdown: $($e.TimeCreated)"
        }
    } else { Write-Report "  No 6008 records" }
} catch { Write-Report "  Read failed: $($_.Exception.Message)" }

# 4. Minidump files
Write-Report "" "Minidump files (C:\Windows\Minidump\)"
$minidumpPath = "C:\Windows\Minidump"
if (Test-Path $minidumpPath) {
    $dumps = Get-ChildItem $minidumpPath -Filter "*.dmp" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending
    if ($dumps) {
        foreach ($d in $dumps) {
            $sizeKB = [Math]::Round($d.Length / 1KB, 1)
            Write-Report "  $($d.Name)  |  $($d.LastWriteTime)  |  $sizeKB KB"
        }
    } else { Write-Report "  No .dmp files (ensure small memory dump is enabled)" }
} else { Write-Report "  Minidump folder not found" }

# 5. Full memory dump
Write-Report "" "Full memory dump (C:\Windows\MEMORY.DMP)"
$memDump = "C:\Windows\MEMORY.DMP"
if (Test-Path $memDump) {
    $f = Get-Item $memDump -ErrorAction SilentlyContinue
    $sizeMB = [Math]::Round($f.Length / 1MB, 2)
    Write-Report "  Exists: $($f.LastWriteTime) | $sizeMB MB"
} else { Write-Report "  Not present (or full dump disabled)" }

# 6. How to enable minidump (if not enabled)
Write-Report "" "If no dumps appear"
Write-Report "  Enable small memory dump: System Properties > Advanced > Startup and Recovery > Settings"
Write-Report "  Set 'Write debugging information' to 'Small memory dump (256 KB)'"
Write-Report "  Dump file: %SystemRoot%\Minidump"

$Report | Set-Content -Path $ReportFile -Encoding UTF8 -NoNewline
Write-Host "Report saved: $ReportFile" -ForegroundColor Green
