@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 936 >nul 2>&1
cd /d "%~dp0"
title KMS 激活工具

rem ---------------- 配置 ----------------
set "KMS_SERVER=kms.wzh.one"
set "KMS_PORT=1688"
set "TCP_TIMEOUT_MS=1800"

rem 0 = Windows 已激活时不替换当前密钥
rem 1 = 强制将受支持的 Windows 版本切换为 KMS 客户端密钥
set "FORCE_WINDOWS_KMS=0"

rem 1 = 检测并激活 Office 批量许可产品
set "ACTIVATE_OFFICE=1"

rem 1 = 执行结束后暂停
set "PAUSE_AT_END=1"
rem --------------------------------------

rem 检查管理员权限
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
 "$p=New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()); if($p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){exit 0}else{exit 1}" >nul 2>&1
if errorlevel 1 (
    echo 正在请求管理员权限...
    powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -Verb RunAs" >nul 2>&1
    if errorlevel 1 (
        mshta "vbscript:CreateObject(""Shell.Application"").ShellExecute(""%~s0"","""","""",""runas"",1)(window.close)"
    )
    exit /b
)

set "OVERALL_RC=0"
set "WINDOWS_RESULT=未执行"
set "WINDOWS_KMS_OK=0"
set "OFFICE_FOUND=0"
set "OFFICE_KMS_FOUND=0"
set "OFFICE_OK=0"
set "OFFICE_FAIL=0"
set "OFFICE_SKIPPED=0"

echo ============================================================
echo                      KMS 激活工具
echo ============================================================
echo.

call :ActivateWindows
echo.

if "%ACTIVATE_OFFICE%"=="1" (
    call :ActivateOffice
) else (
    echo [Office] 已在配置中关闭 Office 激活。
)

echo.
echo ======================== 执行结果 ==========================
echo Windows：!WINDOWS_RESULT!
if "!OFFICE_FOUND!"=="0" (
    echo Office ：未检测到受支持的 Office 安装
) else (
    echo Office ：检测路径 !OFFICE_FOUND! 个，批量许可 !OFFICE_KMS_FOUND! 个，成功 !OFFICE_OK! 个，失败 !OFFICE_FAIL! 个，跳过 !OFFICE_SKIPPED! 个
)
echo ============================================================

if "%PAUSE_AT_END%"=="1" pause
exit /b !OVERALL_RC!


:ActivateWindows
echo [Windows] 正在检查激活状态...

call :WindowsLicensed
if not errorlevel 1 if "!FORCE_WINDOWS_KMS!"=="0" (
    set "WINDOWS_RESULT=已激活，未修改现有密钥"
    echo [Windows] 系统已经激活，已跳过密钥替换。
    exit /b 0
)

call :GetWindowsInfo
if not defined BUILD (
    set "WINDOWS_RESULT=无法读取系统版本"
    set "OVERALL_RC=1"
    echo [Windows][错误] 无法读取 Windows 内部版本号。
    exit /b 1
)
if not defined EDITION_ID (
    set "WINDOWS_RESULT=无法读取系统版本"
    set "OVERALL_RC=1"
    echo [Windows][错误] 无法读取 EditionID。
    exit /b 1
)

call :GetWindowsGVLK
echo [Windows] 产品名称：!PRODUCT_NAME!
echo [Windows] 系统系列：!WINDOWS_FAMILY!
echo [Windows] EditionID：!EDITION_ID!，Build：!BUILD!

if not defined GVLK (
    set "WINDOWS_RESULT=当前版本不受支持"
    set "OVERALL_RC=1"
    echo [Windows][错误] 当前系统版本没有匹配的 KMS 客户端密钥，脚本未安装任何备用密钥。
    exit /b 1
)

echo [Windows] 正在检测 %KMS_SERVER%:%KMS_PORT%...
call :TestTcp "%KMS_SERVER%" "%KMS_PORT%" "%TCP_TIMEOUT_MS%"
if errorlevel 1 (
    set "WINDOWS_RESULT=无法连接 KMS 服务器"
    set "OVERALL_RC=1"
    echo [Windows][错误] 无法连接 %KMS_SERVER%:%KMS_PORT%。
    exit /b 1
)

echo [Windows] 正在安装匹配的 KMS 客户端密钥...
cscript //Nologo "%SystemRoot%\System32\slmgr.vbs" /ipk !GVLK! >nul 2>&1
if errorlevel 1 (
    set "WINDOWS_RESULT=密钥安装失败"
    set "OVERALL_RC=1"
    echo [Windows][错误] KMS 客户端密钥安装失败。
    exit /b 1
)

echo [Windows] 正在设置 KMS 服务器...
cscript //Nologo "%SystemRoot%\System32\slmgr.vbs" /skms %KMS_SERVER%:%KMS_PORT% >nul 2>&1
if errorlevel 1 (
    set "WINDOWS_RESULT=服务器设置失败"
    set "OVERALL_RC=1"
    echo [Windows][错误] 无法设置 KMS 服务器。
    exit /b 1
)

echo [Windows] 正在执行激活...
cscript //Nologo "%SystemRoot%\System32\slmgr.vbs" /ato >nul 2>&1
call :WindowsLicensed
if not errorlevel 1 (
    set "WINDOWS_KMS_OK=1"
    set "WINDOWS_RESULT=激活成功"
    echo [Windows][成功] Windows 已通过 %KMS_SERVER% 激活。
    exit /b 0
)

set "WINDOWS_RESULT=激活失败"
set "OVERALL_RC=1"
echo [Windows][失败] Windows 激活未成功，请检查系统版本、网络和 KMS 授权状态。
exit /b 1


:GetWindowsInfo
set "EDITION_ID="
set "BUILD="
set "PRODUCT_NAME="

for /f "tokens=2,*" %%A in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v EditionID 2^>nul ^| find /i "EditionID"') do set "EDITION_ID=%%B"
for /f "tokens=2,*" %%A in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentBuildNumber 2^>nul ^| find /i "CurrentBuildNumber"') do set "BUILD=%%B"
for /f "tokens=2,*" %%A in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName 2^>nul ^| find /i "ProductName"') do set "PRODUCT_NAME=%%B"

if not defined BUILD (
    for /f %%B in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).BuildNumber" 2^>nul') do set "BUILD=%%B"
)
if not defined PRODUCT_NAME set "PRODUCT_NAME=未知 Windows 版本"
exit /b 0


:GetWindowsGVLK
set "GVLK="
set "WINDOWS_FAMILY=未知"

rem Windows 8，Build 9200
if "!BUILD!"=="9200" (
    set "WINDOWS_FAMILY=Windows 8"
    if /i "!EDITION_ID!"=="Professional"  set "GVLK=NG4HW-VH26C-733KW-K6F98-J8CK4"
    if /i "!EDITION_ID!"=="ProfessionalN" set "GVLK=XCVCF-2NXM9-723PB-MHCB7-2RYQQ"
    if /i "!EDITION_ID!"=="Enterprise"    set "GVLK=32JNW-9KQ84-P47T8-D8GGY-CWCK7"
    if /i "!EDITION_ID!"=="EnterpriseN"   set "GVLK=JMNMF-RHW7P-DMY6X-RF3DR-X2BQT"
    exit /b 0
)

rem Windows 8.1，Build 9600
if "!BUILD!"=="9600" (
    set "WINDOWS_FAMILY=Windows 8.1"
    if /i "!EDITION_ID!"=="Professional"  set "GVLK=GCRJD-8NW9H-F2CDX-CCM8D-9D6T9"
    if /i "!EDITION_ID!"=="ProfessionalN" set "GVLK=HMCNV-VVBFX-7HMBH-CTY9B-B4FXY"
    if /i "!EDITION_ID!"=="Enterprise"    set "GVLK=MHF9N-XY6XB-WVXMC-BTDCT-MKKG7"
    if /i "!EDITION_ID!"=="EnterpriseN"   set "GVLK=TT4HM-HN7YT-62K67-RGRQJ-JFFXW"
    exit /b 0
)

rem Windows 10/11，Build 10240 及以上
if !BUILD! GEQ 10240 (
    if !BUILD! GEQ 22000 (
        set "WINDOWS_FAMILY=Windows 11"
    ) else (
        set "WINDOWS_FAMILY=Windows 10"
    )

    if /i "!EDITION_ID!"=="Professional"             set "GVLK=W269N-WFGWX-YVC9B-4J6C9-T83GX"
    if /i "!EDITION_ID!"=="ProfessionalN"            set "GVLK=MH37W-N47XK-V7XM9-C7227-GCQG9"
    if /i "!EDITION_ID!"=="ProfessionalWorkstation"  set "GVLK=NRG8B-VKK3Q-CXVCJ-9G2XF-6Q84J"
    if /i "!EDITION_ID!"=="ProfessionalWorkstationN" set "GVLK=9FNHH-K3HBT-3W4TD-6383H-6XYWF"
    if /i "!EDITION_ID!"=="ProfessionalEducation"    set "GVLK=6TP4R-GNPTD-KYYHQ-7B7DP-J447Y"
    if /i "!EDITION_ID!"=="ProfessionalEducationN"   set "GVLK=YVWGF-BXNMC-HTQYQ-CPQ99-66QFC"
    if /i "!EDITION_ID!"=="Education"                set "GVLK=NW6C2-QMPVW-D7KKK-3GKT6-VCFB2"
    if /i "!EDITION_ID!"=="EducationN"               set "GVLK=2WH4N-8QGBV-H22JP-CT43Q-MDWWJ"
    if /i "!EDITION_ID!"=="Enterprise"               set "GVLK=NPPR9-FWDCX-D2C8J-H872K-2YT43"
    if /i "!EDITION_ID!"=="EnterpriseN"              set "GVLK=DPH2V-TTNVB-4X9Q3-TJR4H-KHJW4"
    if /i "!EDITION_ID!"=="EnterpriseG"              set "GVLK=YYVX9-NTFWV-6MDM3-9PT4T-4M68B"
    if /i "!EDITION_ID!"=="EnterpriseGN"             set "GVLK=44RPN-FTY23-9VTTB-MP9BX-T84FV"

    rem Enterprise LTSC/LTSB 根据基础 Build 选择密钥
    if /i "!EDITION_ID!"=="EnterpriseS" (
        if "!BUILD!"=="10240" set "GVLK=WNMTR-4C88C-JK8YV-HQ7T2-76DF9"
        if "!BUILD!"=="14393" set "GVLK=DCPHK-NFMTC-H88MJ-PFHPY-QJ4BJ"
        if !BUILD! GEQ 17763 set "GVLK=M7XTQ-FN8P6-TTKYV-9D4CC-J462D"
    )
    if /i "!EDITION_ID!"=="EnterpriseSN" (
        if "!BUILD!"=="10240" set "GVLK=2F77B-TNFGY-69QQF-B8YKP-D69TJ"
        if "!BUILD!"=="14393" set "GVLK=QFFDN-GRT3P-VKWWX-X7T3R-8B639"
        if !BUILD! GEQ 17763 set "GVLK=92NFX-8DJQP-P6BBQ-THF9C-7CG2H"
    )

    if /i "!EDITION_ID!"=="IoTEnterpriseS" if !BUILD! GEQ 19044 set "GVLK=KBN8V-HFGQ4-MGXVD-347P6-PDQGT"
)
exit /b 0


:WindowsLicensed
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
 "$p=Get-WmiObject -Class SoftwareLicensingProduct -ErrorAction SilentlyContinue | Where-Object {$_.ApplicationID -eq '55c92734-d682-4d71-983e-d6ec3f16059f' -and $_.PartialProductKey -and -not $_.LicenseIsAddon -and $_.LicenseStatus -eq 1}; if($p){exit 0}else{exit 1}" >nul 2>&1
exit /b %ERRORLEVEL%


:ActivateOffice
echo [Office] 正在查找 Office 批量许可组件...

call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\root\Office16"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\root\Office16"
call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\Office16"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\Office16"

call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\root\Office15"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\root\Office15"
call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\Office15"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\Office15"

call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\root\Office14"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\root\Office14"
call :ProcessOfficePath "%ProgramFiles%\Microsoft Office\Office14"
call :ProcessOfficePath "%ProgramFiles(x86)%\Microsoft Office\Office14"

if "!OFFICE_FOUND!"=="0" (
    echo [Office] 未找到受支持的 Office 安装。
) else if "!OFFICE_KMS_FOUND!"=="0" (
    echo [Office] 已找到 Office，但未检测到 VOLUME_KMSCLIENT 批量许可产品。
    echo [Office] 零售版和 Microsoft 365 订阅版不会被修改。
)
exit /b 0


:ProcessOfficePath
set "OPATH=%~1"
if not exist "!OPATH!\ospp.vbs" exit /b 0

set /a OFFICE_FOUND+=1
set "OGEN=16"
if /i not "!OPATH:Office14=!"=="!OPATH!" set "OGEN=14"
if /i not "!OPATH:Office15=!"=="!OPATH!" set "OGEN=15"

echo [Office] 检测到：!OPATH!

set "STATUS_FILE=%TEMP%\kms_ospp_!RANDOM!_!RANDOM!.tmp"
cscript //Nologo "!OPATH!\ospp.vbs" /dstatusall >"!STATUS_FILE!" 2>&1

findstr /i /c:"VOLUME_KMSCLIENT" "!STATUS_FILE!" >nul 2>&1
if errorlevel 1 (
    set /a OFFICE_SKIPPED+=1
    echo [Office] 此路径未检测到 KMS 客户端许可，已跳过。
    del /q "!STATUS_FILE!" >nul 2>&1
    exit /b 0
)

set /a OFFICE_KMS_FOUND+=1
echo [Office] 正在检测 %KMS_SERVER%:%KMS_PORT%...
call :TestTcp "%KMS_SERVER%" "%KMS_PORT%" "%TCP_TIMEOUT_MS%"
if errorlevel 1 (
    set /a OFFICE_FAIL+=1
    set "OVERALL_RC=1"
    echo [Office][错误] 无法连接 %KMS_SERVER%:%KMS_PORT%。
    del /q "!STATUS_FILE!" >nul 2>&1
    exit /b 1
)

echo [Office] 正在设置 KMS 服务器并执行激活...
cscript //Nologo "!OPATH!\ospp.vbs" /sethst:%KMS_SERVER% >nul 2>&1
cscript //Nologo "!OPATH!\ospp.vbs" /setprt:%KMS_PORT% >nul 2>&1
cscript //Nologo "!OPATH!\ospp.vbs" /act >nul 2>&1

call :OfficeGenerationLicensed "!OGEN!"
if not errorlevel 1 (
    set /a OFFICE_OK+=1
    echo [Office][成功] 此路径下的 KMS 客户端产品已激活。
) else (
    set /a OFFICE_FAIL+=1
    set "OVERALL_RC=1"
    echo [Office][失败] 此路径下仍有 KMS 客户端产品未激活。
)

del /q "!STATUS_FILE!" >nul 2>&1
exit /b 0


:OfficeGenerationLicensed
set "OFFICE_GEN=%~1"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
 "$items=@(); switch('%OFFICE_GEN%'){'14'{$app='59a52881-a989-479d-af46-f275c6370663';$pat='Office 14'}'15'{$app='0ff1ce15-a989-479d-af46-f275c6370663';$pat='Office 15'}default{$app='0ff1ce15-a989-479d-af46-f275c6370663';$pat='Office (16|19|21|24)'}}; try{$items+=@(Get-WmiObject -Class SoftwareLicensingProduct -ErrorAction Stop | Where-Object {$_.ApplicationID -eq $app})}catch{}; try{$items+=@(Get-WmiObject -Class OfficeSoftwareProtectionProduct -ErrorAction Stop | Where-Object {$_.ApplicationID -eq $app})}catch{}; $kms=@($items | Where-Object {$_.PartialProductKey -and $_.Description -match 'VOLUME_KMSCLIENT' -and $_.Description -match $pat}); $bad=@($kms | Where-Object {$_.LicenseStatus -ne 1}); if($kms.Count -gt 0 -and $bad.Count -eq 0){exit 0}else{exit 1}" >nul 2>&1
exit /b %ERRORLEVEL%


:TestTcp
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
 "$ok=$false; $c=New-Object Net.Sockets.TcpClient; try{$a=$c.BeginConnect('%~1',[int]%~2,$null,$null); if($a.AsyncWaitHandle.WaitOne([int]%~3,$false)){$c.EndConnect($a);$ok=$true}}catch{}finally{$c.Close()}; if($ok){exit 0}else{exit 1}" >nul 2>&1
exit /b %ERRORLEVEL%
