# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
#
# PyWin32Info
# Copyright (C) 2005 Michele Baldessari <michele@pupazzo.org>

# This file may be distributed and/or modified under the terms of
# the GNU General Public License version 2 as published by
# the Free Software Foundation.
# This file is distributed without any warranty; without even the implied
# warranty of merchantability or fitness for a particular purpose.
# See "LICENSE.GPL" in the source distribution for more information.

import wmi
import win32api
import win32con
import smtplib
import datetime
import traceback, sys

class Win32InfoCollector:
    def __init__(self):
        self.w = wmi.WMI()

    def getMacAddresses(self):
        ifaces = self.w.Win32_NetworkAdapterConfiguration (IPEnabled=1)
        tmp = []
        for i in ifaces:
            tmp.append((i.Description, i.MACAddress, i.IPAddress))

        return tmp

    def getOsInfoRegistry(self):
        s = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"
        key = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, s, win32con.KEY_ALL_ACCESS)
        counter = 0
        tmp = {}
        wantedfields = ['ProductInfo', 'SystemRoot', 'CurrentType', 'CurrentVersion',
                        'RegisteredOwner', 'RegisteredOrganization', 'ProductName',
                        'InstallDate']
        
        while 1:
            try:
                (k, v, t) = win32api.RegEnumValue(key, counter)
                if k in wantedfields:
                    tmp[k] = v
                counter = counter + 1
            except:
                break
        return tmp
    
    def getStartupCommands(self):
        tmp = []
        for s in self.w.Win32_StartupCommand ():
            tmp.append((s.Location, s.Caption, s.Command))
        return tmp
            
    def getProcessList(self):
        tmp = []
        for process in self.w.Win32_Process():
            tmp.append((process.ProcessId, process.Name, process.Description, process.WorkingSetSize))
        return tmp

    def getDefaultUser(self):
        user = ""
        s = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon"
        try:
            key = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, s, win32con.KEY_ALL_ACCESS)
            (user, veluetype) = win32api.RegQueryValueEx(key, "DefaultUserName")
        except:
            pass
        return user

    def getInstalledSoftware(self):
        s = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstalled\\"
        try:
            key = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, s, win32con.KEY_ALL_ACCESS)
            while 1:
                (user, veluetype) = win32api.RegQueryValueEx(key, "DefaultUserName")
        except:
            pass

    def getPhysicalMemory(self):
        t = self.w.Win32_LogicalMemoryConfiguration ()
        tot_mem = 0
        tot_swap = 0
        for i in t:
            tot_mem  = tot_mem  + i.TotalPhysicalMemory
            tot_swap = tot_swap + i.TotalPageFileSpace

        return (tot_mem, tot_swap)

    def getServiceList(self):
        t = self.w.Win32_Service ()
        tmp = []
        for i in t:
            tmp.append((i.DisplayName, i.Description, i.PathName, i.State, i.StartMode))
        return tmp

    def getLogErrors(self):
        t = self.w.Win32_NTLogEvent ()
        tmp = []
        for i in t:
            tmp.append(i)
        return tmp

    def getScheduledTasks (self):
        t = self.w.Win32_ScheduledJob ()
        return "FIXME"

    def getPrinterList (self):
        t = self.w.Win32_Printer ()
        tmp = []
        for i in t:
            tmp.append((i.Name, i.DriverName, i.Default, i.Local))
        return tmp

    def getDate (self):
        t = self.w.Win32_LocalTime ()
        i = t[0]
        return (i.Year, i.Month, i.Day, i.Hour, i.Minute, i.Second)

    def getOsInfo (self):
        t = self.w.Win32_OperatingSystem ()
        wantedfields = [ "BootDevice", "BuildNumber", "BuildType", "Caption", "CodeSet", "CountryCode", "CSDVersion",
                         "CSName", "CurrentTimeZone", "Description", "InstallDate", "LastBootupTime",  "Manufacturer", "NumberOfUsers",
                         "NumberOfProcesses", "Name", "RegisteredUser", "OSLanguage", "OSType", "Status", "SystemDirectory", "SystemDrive",
                         "Version", "WindowsDirectory" ]
        os = t[0]
        tmp = {}
        for i in wantedfields:
            if hasattr(os, i):
                tmp[i] = getattr(os, i)
        return tmp

    def getComputerInfo (self):
        t = self.w.Win32_ComputerSystem ()
        wantedfields = ["BootupState", "Caption", "Description", "Domain", "DomainRole", "Manufacturer",
                        "Model", "Name", "NetworkServerModeEnabled", "NumberOfProcessors", "OEMStringArray",
                        "PartOfDomain", "PrimaryOwnerName", "Roles", "Status", "SystemType", "TotalPhysicalMemory",
                        "UserName"]
        computer = t[0]
        tmp = {}
        for i in wantedfields:
            if hasattr(computer, i):
                tmp[i] = getattr(computer, i)
        return tmp

    def getDiskList (self):
        tmp = []
        wantedfields = [ "Caption", "Compressed", "Description", "FileSystem", "FreeSpace", "Size", "VolumeName",
                         "VolumeSerialNumber", "DeviceID"]
        for disk in self.w.Win32_LogicalDisk (DriveType=3):
            entry = {}
            for i in wantedfields:
                if hasattr(disk, i):
                    entry[i] = getattr(disk, i)
            tmp.append(entry)
        return tmp

    def getPrinterList (self):
        printerlist = self.w.Win32_Printer ()
        print printerlist
        tmp = []
        wantedfields = [ "Caption", "Default", "Direct", "DriverName", "Local", "Network", "Name",
                         "PortName", "Shared", "Status", "SystemName", "DeviceID"]
        for printer in self.w.Win32_Printer():
            entry = {}
            for i in wantedfields:
                if hasattr(printer, i):
                    entry[i] = getattr(printer, i)
            tmp.append(entry)
        return tmp

class MailReport:
    def __init__(self, sender, receivers, smtpserver, subject="PyWin32Info"):
        self.smtpserver = smtpserver
        self.fromaddr = sender
        self.toaddrs  = receivers
        self.subject  = subject
        self.header = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n"
            % (self.fromaddr, ", ".join(self.toaddrs), self.subject))
        self.msg = self.header

    def addText(self, txt):
        self.msg = self.msg + txt + "\n" 

    def send(self, debuglevel=1):    
        server = smtplib.SMTP(self.smtpserver)
        server.set_debuglevel(debuglevel)
        server.sendmail(self.fromaddr, self.toaddrs, self.msg)
        server.quit()

def maxstring(str, maxlen):
    if len(str) > maxlen:
        s = str[0:maxlen-3] + "..."
        return s
    else:
        return str
        
def makeFormattedReport(info):
    s = ""
    col = 60
    now = datetime.datetime.today().strftime("%Y-%m-%d %H:%M")
    s = "Info generated on " + now + "\n\n"

    try:
        s = s + "Default user: " + info.getDefaultUser() + "\n"
        mem = info.getPhysicalMemory()
        s = s + "Physical memory: " + str(mem[0]) + " MByte - Swap :" + str(mem[1]) + " MByte\n"
        d = info.getDate()
        s = s + "Date on machine %d-%d-%d %d:%d" % (d[0], d[1], d[2], d[3], d[4])
        s = s + "\n\nMac Addresses:\n"
        mac = info.getMacAddresses()
        for i in mac:
            s = s + i[0] + "\n"
            s = s + "%-18s " % (i[1])
            for k in i[2]:
                s = s + "%s " % (k)
            s = s + "\n"

        s = s + "\n\nComputer\n"
        s = s + "-"*col
        s = s + "\n"
        so = info.getOsInfoRegistry()
        s = s + "%s - Owner: %s - Organization: %s\n" % (so['ProductName'], so['RegisteredOwner'], so['RegisteredOrganization'])
        computer = info.getComputerInfo()
        for (k,v) in computer.items():
            s = s + "%s: %s\n" % (k, v)

        s = s + "\n\nOperating System\n"
        s = s + "-"*col
        s = s + "\n"
        s = s + "\n"
        os = info.getOsInfo()
        for (k,v) in os.items():
            s = s + "%s: %s\n" % (k, v)

    except:
        traceback.print_exc(file=sys.stdout)
        pass

    s = s + "\n\nHard Disks\n"
    s = s + "-"*col
    s = s + "\n"
    try:
        disks = info.getDiskList()
        for i in disks:
            s = s + "[%s]\n" % (i['DeviceID'])
            for (k, v) in i.items():
                s = s + "%s: %s\n" % (k, v)
            s = s + "Free: %0.2f%%\n\n" % (100.0 * long (i['FreeSpace']) / long (i['Size']))
    except:
        traceback.print_exc(file=sys.stdout)
        pass

    s = s + "\n\nStampanti\n"
    s = s + "-"*col
    s = s + "\n"
    try:
        printers = info.getPrinterList()
        for i in printers:
            s = s + "[%s]\n" % (i['DeviceID'])
            for (k, v) in i.items():
                s = s + "%s: %s\n" % (k, v)
            s = s + "\n"
    except:
        traceback.print_exc(file=sys.stdout)
        pass




    s = s + "\n\nProcess List\n"
    s = s + "-"*col
    s = s + "\n"
    try:
        procs = info.getProcessList()
        for i in procs:
            s = s + "%5s %20s - %9s bytes" % (i[0], i[1], i[3])
            s = s + "\n"
    except:
        traceback.print_exc(file=sys.stdout)
        pass

    s = s + "\nService List\n"
    s = s + "-"*col
    s = s + "\n"
    try:
        services = info.getServiceList()
        for i in services:            
            s = s + "%-36s %-50s %-8s %-8s\n" % (maxstring(i[0],35), maxstring(i[2],50), i[3], i[4])
    except:
        traceback.print_exc(file=sys.stdout)
        pass

    return s    

if __name__ == '__main__':
    test = Win32InfoCollector()
    mail = MailReport("michele@pupazzo.org", ["michele@pupazzo.org"], "smtp.fastwebnet.it")
    s = makeFormattedReport(test)
    mail.addText(s.encode('ascii', 'ignore'))
    mail.send()
    #test.getPrinterList()
    print s

