Option Explicit
' 2-kill.vbs -- double-click. It asks for admin by itself.
'   1) stop service zmserv (WMI, no external program)
'   2) wait until zmserv.exe PROCESS is really gone
'   3) kill every target in ONE WMI pass (the judge revives them in 3 s)
' Output: C:\Users\Public\tool\kill.txt
Const LOGF = "C:\Users\Public\tool\kill.txt"

Dim fso, sh, wmi, p, rc, i, ok, killed, remain, judgeName, judgePid, svc

Set fso = CreateObject("Scripting.FileSystemObject")
Set sh = CreateObject("WScript.Shell")
If Not fso.FolderExists("C:\Users\Public\tool") Then fso.CreateFolder "C:\Users\Public\tool"

If Not IsAdmin() Then
  CreateObject("Shell.Application").ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """", "", "runas", 1
  WScript.Quit 0
End If

Set wmi = GetObject("winmgmts:")
L "START " & Now

L "=== 1. stop service"
Set svc = Nothing
On Error Resume Next
Err.Clear
Set svc = wmi.Get("Win32_Service.Name='zmserv'")
If Err.Number <> 0 Then
  L "  service not found, skip"
  Err.Clear
Else
  rc = svc.StopService()
  L "  StopService rc=" & rc
  If rc = 5 Then
    MsgBox "No administrator rights. Double-click again and click Yes.", 16, "2-kill"
    WScript.Quit 1
  End If
End If
On Error GoTo 0

L "=== 2. wait for zmserv.exe to exit"
ok = False
For i = 1 To 20
  If ProcCount("zmserv.exe") = 0 Then
    ok = True
    L "  gone after check " & i
    Exit For
  End If
  WScript.Sleep 500
Next
If Not ok Then
  L "  zmserv.exe still alive after 10 s -- ABORT (do not kill, it would power off)"
  MsgBox "Service process did not exit. Aborted on purpose.", 16, "2-kill"
  WScript.Quit 2
End If

L "=== 3. one WMI pass"
judgeName = ""
judgePid = 0
For Each p In wmi.ExecQuery("Select Name,ProcessId from Win32_Process")
  If IsTarget(LCase(p.Name), "") Then
    If judgeName = "" And LCase(p.Name) <> "jfglzsn.exe" And LCase(p.Name) <> "zmserv.exe" Then
      judgeName = p.Name
      judgePid = p.ProcessId
    End If
  End If
Next
L "  judge = " & judgeName & " pid=" & judgePid

killed = 0
For Each p In wmi.ExecQuery("Select Name,ProcessId from Win32_Process")
  If IsTarget(LCase(p.Name), "") Then
    rc = 999
    On Error Resume Next
    Err.Clear
    rc = p.Terminate()
    If Err.Number <> 0 Then
      rc = "err " & Err.Number
      Err.Clear
    End If
    On Error GoTo 0
    L "  kill " & p.Name & " pid=" & p.ProcessId & " rc=" & rc
    killed = killed + 1
  End If
Next
L "  killed = " & killed

L "=== 4. recheck after 5 s"
WScript.Sleep 5000
remain = 0
For Each p In wmi.ExecQuery("Select Name,ProcessId from Win32_Process")
  If IsTarget(LCase(p.Name), "") Then
    L "  still alive: " & p.Name & " pid=" & p.ProcessId
    remain = remain + 1
  End If
Next
L "  remain = " & remain
L "DONE"

If remain = 0 Then
  MsgBox "OK. killed=" & killed & "  remain=0" & vbCrLf & vbCrLf & "judge was " & judgeName & vbCrLf & vbCrLf & "Next: double-click 3-restore.vbs", 64, "2-kill OK"
Else
  MsgBox "Still alive: " & remain & ". See kill.txt", 48, "2-kill FAILED"
  WScript.Quit 3
End If

Sub L(t)
  Dim ff
  Set ff = fso.OpenTextFile(LOGF, 8, True)
  ff.WriteLine t
  ff.Close
End Sub

Function IsAdmin()
  IsAdmin = True
  On Error Resume Next
  Err.Clear
  sh.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\__probe", 1, "REG_DWORD"
  If Err.Number <> 0 Then IsAdmin = False
  Err.Clear
  sh.RegDelete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\__probe"
  Err.Clear
  On Error GoTo 0
End Function

Function ProcCount(nm)
  Dim q
  ProcCount = 0
  For Each q In wmi.ExecQuery("Select ProcessId from Win32_Process Where Name='" & nm & "'")
    ProcCount = ProcCount + 1
  Next
End Function

Function AllInRange(t, lo, hi)
  Dim i, ch
  AllInRange = False
  For i = 1 To Len(t)
    ch = Asc(Mid(t, i, 1))
    If ch < lo Or ch > hi Then Exit Function
  Next
  AllInRange = True
End Function

Function IsTarget(b, pth)
  Dim base
  IsTarget = False
  base = LCase(b)
  If Right(base, 4) = ".exe" Then base = Left(base, Len(base) - 4)
  If base = "jfglzsn" Or base = "zmserv" Or base = "przs" Then
    IsTarget = True
    Exit Function
  End If
  If Len(base) = 5 And AllInRange(base, 105, 114) Then IsTarget = True
  If Len(base) = 4 And AllInRange(base, 97, 106) Then
    If InStr(LCase(pth & ""), "\program files (x86)\") > 0 Then IsTarget = True
  End If
End Function
