
import os
import ctypes
import ssl
import urllib2
import _winreg
from subprocess import PIPE, Popen

# ===============================
# Mandatory Parameters (set in portal)
# ===============================
msi_url = itsm.getParameter('download_url')
site_token = itsm.getParameter('token')

# ===============================
# File System Redirection Context
# ===============================
class disable_file_system_redirection:
    _disable = ctypes.windll.kernel32.Wow64DisableWow64FsRedirection
    _revert = ctypes.windll.kernel32.Wow64RevertWow64FsRedirection
    def __enter__(self):
        self.old_value = ctypes.c_long()
        self.success = self._disable(ctypes.byref(self.old_value))
    def __exit__(self, type, value, traceback):
        if self.success:
            self._revert(self.old_value)

# ===============================
# Build Silent Arguments (only required ones)
# ===============================
silent_arguments = '/quiet /norestart SITE_TOKEN="{0}"'.format(site_token)

# ===============================
# Detect SentinelOne
# ===============================
def is_sentinelone_installed():
    try:
        with disable_file_system_redirection():
            check_cmd = 'powershell -Command "Get-Service -Name SentinelAgent -ErrorAction SilentlyContinue"'
            p = Popen(check_cmd, shell=True, stdout=PIPE, stderr=PIPE)
            out, err = p.communicate()
            if "Running" in out or "Stopped" in out:
                print("SentinelOne service detected. Agent is installed.")
                return True
    except Exception as e:
        print("Service check failed: %s" % str(e))

    # Fallback: Registry uninstall entries
    try:
        uninstall_paths = [
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
            r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
        ]
        for path in uninstall_paths:
            try:
                key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, path)
                for i in range(0, _winreg.QueryInfoKey(key)[0]):
                    try:
                        subkey_name = _winreg.EnumKey(key, i)
                        subkey = _winreg.OpenKey(key, subkey_name)
                        display_name, _ = _winreg.QueryValueEx(subkey, "DisplayName")
                        if "Sentinel" in display_name or "Agent" in display_name:
                            print("SentinelOne uninstall entry found: %s" % display_name)
                            return True
                    except:
                        continue
            except:
                continue
    except:
        pass

    print("SentinelOne is not installed.")
    return False

# ===============================
# File Download and Install
# ===============================
def downloadFile(dest, fromURL):
    headers = {'User-Agent': 'Mozilla/5.0'}
    context = ssl._create_unverified_context()
    request = urllib2.Request(fromURL, headers=headers)
    try:
        response = urllib2.urlopen(request, context=context)
        with open(dest, 'wb') as f:
            while True:
                chunk = response.read(1000000)
                if not chunk:
                    break
                f.write(chunk)
        return os.path.isfile(dest)
    except:
        return False

def install():
    if not msi_url or not site_token:
        print("Missing required parameters: msi_url or site_token.")
        return

    if is_sentinelone_installed():
        print("SentinelOne is already installed. No action needed.")
        return

    print("SentinelOne not found. Proceeding with installation...")
    temp_path = os.environ['TEMP']
    file_name = "SentinelOneInstaller.msi"
    msi_file = os.path.join(temp_path, file_name)

    print("Downloading SentinelOne MSI from: " + msi_url)
    if downloadFile(msi_file, msi_url):
        print("Download complete. Starting installation...")
        with disable_file_system_redirection():
            obj = Popen('msiexec /i "%s" %s' % (msi_file, silent_arguments), shell=True, stdout=PIPE, stderr=PIPE)
            out, err = obj.communicate()
            if obj.returncode == 0:
                print("SentinelOne installed successfully.")
            elif obj.returncode == 3010:
                print("Installation successful, reboot required (3010).")
            else:
                print("Installation failed. Error code: %s" % obj.returncode)
                if err:
                    print(err)
    else:
        print("Failed to download the MSI file. Check the URL or network access.")
    
    try:
        os.remove(msi_file)
    except:
        pass

# ===============================
# Run Installer
# ===============================
install()
