# Copyright 2026 SigmaSRC, Inc. All Rights Reserved.

"""Gather script for software version #'s in Windows."""


import os
import time
import tempfile

from sigma.util import console

# All the field names VBS can gather
FIELDNAMES = """
Attributes
BuildNumber
Caption
CodeSet
Description
IdentificationCode
InstallDate
InstallState
LanguageEdition
Manufacturer
Name
OtherTargetOS
Path
SerialNumber
SoftwareElementID
SoftwareElementState
Status
TargetOperatingSystem
Version
""".split()

# Template for VBS script; the %s becomes a bunch of Wscript.Echo commands
TEMPLATE = """
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\\\" & strComputer & "\\root\\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_SoftwareElement",,48)
For Each objItem in colItems
    %s
    Wscript.Echo "---"
Next
"""

def Gather(collector):
    # write header to output
    table = collector.table("winswvers", FIELDNAMES)
    for fields in gather_helper(FIELDNAMES):
        table.add(fields)

def gather_helper(fieldnames):
    if os.name != "nt":
        raise RuntimeError("Can only gather Windows software version info on Windows")

    # create the VBS script text
    statements = ["    Wscript.Echo objItem.%s\n" % fn for fn in fieldnames]
    vbscript = TEMPLATE % "".join(statements)

    # create a temp file and stuff the VBS script into it
    tfn = tempfile.mktemp(".vbs")
    try:
        tmp = open(tfn, "w")
        try:
            tmp.write(vbscript)
        finally:
            tmp.close()

        # cscript is the command-line VBS interpreter;
        # //nologo kills off some crufty output
        command = "cscript //nologo " + tfn
        p = console.popen(command, "r")
        rawdata = p.readlines()
        sts = p.close()
        if sts:
            raise RuntimeError("Nonzero exit status from VBS script: %s" % sts)
    finally:
        if os.path.exists(tfn):
            os.remove(tfn)

    # write process entries to output
    ncolumns = len(fieldnames)
    current = []
    for line in rawdata:
        if line == "---\n":
            assert len(current) == ncolumns
            yield current
            current = []
            continue
        field = line.strip()
        if field == "null":
            field = ""
        current.append(field)
    assert not current

def _test():
    from sigma.gather import gathering
    gathering.test(Gather)

if __name__ == "__main__":
    _test()
