;; 
;;=====================================================================================----- 
;; 
;;FUNCTION       ReadEventlog() 
;; 
;;ACTION         Retrieves events from the eventlog 
;; 
;;AUTHOR         Jens Meyer 
;; 
;;CONTRIBUTORS   Glenn Barnas - code update, minor fixes 
;; 
;;VERSION        1.6  - 2017/11/17 
;; 
;;HISTORY        1.0  - 2001/12/22 - Initial Release 
;;               1.51 - 2004/01/09 -  
;;               1.6  - 2017/11/17 - Glenn Barnas; update code standards, fix EventID processing 
;; 
;;SYNTAX         ReadEventlog(EventLog[, EvtID][, Computer][, DateTime][, UserName][, Password])  
;; 
;;PARAMETERS     EventLog   - REQUIRED - Name of the eventlog: Security, System, Application 
;;               Alternatively, a custom WQL query can be provided. Date fields in a  
;;               WQL query MUST be properly formatted in the WMI date-time format as  
;;               YYYYMMDDHHMMSS.000000-UUU where -UUU is the three-digit offset  
;;               indicating the number of minutes that the originating time zone  
;;               deviates from UTC. For WMI, it is encouraged, but not required,  
;;               to convert times to GMT (a UTC offset of zero). 
;;               See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/sql_for_wmi.asp 
;;                
;;               EvtID      - OPTIONAL - Event ID number to be retrieved 
;; 
;;               Computer   - OPTIONAL - name of a remote computer which eventlog is to  
;;               be queried. If no username/password is provided then the current users  
;;               credentials will be used to connect to the remote event log. 
;; 
;;               DateTime   - OPTIONAL - date/time string denoting the start date of the  
;;               events in the form of YYYY/MM/DD HH:MM:SS,YYYY/MM/DD, or HH:MM:SS 
;; 
;;               UserName   - OPTIONAL - name which will be used to connect  
;;               to a remote computer 
;; 
;;               Password   - OPTIONAL - password which will be used to connect  
;;               to the remote computer 
;; 
;;REMARKS         
;; 
;;RETURNS        2-dimensional array of events or empty string 
;;                with the following columns. If custom WQL is used, then the SELECT  
;;               part of the custom WQL determines the field assignments. 
;;                Column 0 = Category  
;;                Column 1 = CategoryString  
;;                Column 2 = ComputerName  
;;                Column 3 = Data  
;;                Column 4 = EventCode  
;;                Column 5 = EventIdentIfier 
;;                 (see http://support.microsoft.com/default.aspx?scid=kb;en-us;245222)  
;;                Column 6 = EventType  
;;                Column 7 = InsertionStrings  
;;                Column 8 = Logfile  
;;                Column 9 = Message  
;;                Column 10 = RecordNumber  
;;                Column 11 = Source Name  
;;                Column 12 = TimeGenerated  
;;                Column 13 = TimeWritten  
;;                Column 14 = Type  
;;                Column 15 = User  
;; 
;;DEPENDENCIES   WMI 
;; 
;;TESTED WITH    W2K12r2, W2K16, W10 (originally tested on 2K3 and above) 
;; 
;;EXAMPLES        
;;                $events = ReadEventlog('Security',528)  
;;                $events = ReadEventlog('Security',528,'COMPUTER')  
;;                $events = ReadEventlog('Security',528,'COMPUTER','2016/09/01 00:00:00','Administrator','password')  
;;                $events = ReadEventlog('SELECT TimeGenerated, User FROM Win32_NTLogEvent  
;;                 WHERE Logfile="Security" AND EventCode=528 AND  
;;                 TimeGenerated>="20020901000000.000000-240"')  
; 
Function ReadEventlog($_eventlog, optional $_eventid, $_computer, $_datetime, $_username, $_password) 
  Dim $_objLocator								;  
  Dim $_objWBEM									;  
  Dim $_objWMIResults								;  
  Dim $_namespace								;  
;  Dim $_objWMIResultsCopy 							;  
  Dim $_event									;  
  Dim $_item									;  
  Dim $_wqlQuery								; Query String 
  Dim $_customwql								; custom Query String 
  Dim $_customfields								; custom query fields 
  Dim $_itemvalue 								;  
  Dim $_eventarray								; array of event data 
  Dim $_itemname								;  
;  Dim $_field 									;  
  Dim $_rownumber								;  
  Dim $_arrayrows								;  
  Dim $_arraycolumns								;  
  Dim $_columnnumber 								;  
  Dim $_byte									;  
  Dim $_datastring								;  
  Dim $_date									; Date string 
  Dim $_time									; Time string 
;  Dim $_querydate								;  
;  Dim $_querytime								;  
  Dim $_timezone 								; local timezone 
  Dim $_objWMIService, $_colItems, $_objItem 					; WMI query objects 
 
  $_namespace = 'root\CIMV2' 
  $_arrayrows=50 
 
  If Trim($_eventlog)='' 
    Exit 87 
  EndIf 
 
  ; check to see whether we're connecting to a local or remote eventlog  
  $_computer=Trim($_computer) 
  Select 
   Case $_computer = @WKSTA 
    $_computer='.' 
   Case $_computer 
   Case 1 
    $_computer='.' 
  EndSelect 
 
  If $_username And $_computer <> '.' 
    ; create locator object for connection to a remote computer  
    $_objLocator = CreateObject('WbemScripting.SWbemLocator') 
    If @ERROR 
      Exit @ERROR 
    EndIf 
 
    ; in order to connect to a remote windows xP or Windows Server 2003 computer, the  
    ; authentication level needs to be set to packet and not connect  
    ; WbemAuthenticationLevelConnect = 2  
    ; WbemAuthenticationLevelPkt = 4  
 
    $_objLocator.Security_.AuthenticationLevel = 4 
    If @ERROR 
      Exit @ERROR 
    EndIf 
 
    ; create a credentialed connection to a remote computer  
    $_objWBEM = $_objLocator.ConnectServer($_computer, $_namespace, $_username, $_password) 
    If @ERROR 
      Exit @ERROR 
    EndIf 
    ; set the impersonation level  
    $_objWBEM.Security_.ImpersonationLevel = 3 
    If @ERROR 
      Exit @ERROR 
    EndIf 
  Else 
    ;set the impersonation level And make sure we have security permissions  
    If $_eventlog = 'Security' Or (left($_eventlog, 6)='Select' And InStr($_eventlog, 'Security') And InStr($_eventlog, 'Logfile')) 
      $_objWBEM = GetObject('winmgmts:{impersonationLevel=impersonate, (Security)}!\\' + $_computer + '\' + $_namespace) 
    Else 
      $_objWBEM = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $_computer + '\' + $_namespace) 
    EndIf 
    If @ERROR 
      Exit @ERROR 
    EndIf 
  EndIf 
 
  ; check to see whether we're looking for an event ID or If there's a custom query  
  If Left($_eventlog,6) = 'Select' 
    $_wqlquery = $_eventlog 
    $_arraycolumns = Trim(SubStr($_wqlquery, InStr($_wqlquery, ' ') + 1, InStr($_wqlquery, 'FROM') - InStr($_wqlquery, ' ') - 2)) 
    If InStr($_arraycolumns, '*') 
      $_arraycolumns = 16 
      $_customwql = 0 
    Else 
      $_customfields = Split(Trim($_arraycolumns), ',') 
      For $_arraycolumns = 0 to ubound($_customfields) 
        $_customfields[$_arraycolumns] = Trim($_customfields[$_arraycolumns]) 
      Next
      $_arraycolumns=ubound($_customfields) + 1 
      $_customwql = 1 
    EndIf 
  Else 
    $_customwql = 0 
    $_arraycolumns = 16
 
; GB: Avoided a default EventID of zero, allows returning ALL records 
    $_wqlQuery = "SELECT * FROM Win32_NTLogEvent WHERE Logfile='" + $_eventlog + "'"
    If $_eventid
      $_wqlQuery = $_wqlQuery + ' AND EventCode=' + val($_eventID)
    EndIf
; GB 
 
    If $_datetime 
      $_colItems = $_objWBEM.ExecQuery('Select CurrentTimeZone from Win32_ComputerSystem') 
      If @ERROR 
        Exit @ERROR 
      EndIf 
 
      For Each $_objItem In $_colItems 
        $_timezone = $_objItem.CurrentTimeZone 
      Next 
 
      $_objWMIService = 0 
      $_colItems = 0 
      $_objItem = 0 
 
      $_datetime = Trim($_datetime) 
 
      Select 
       Case InStr($_datetime,' ') 
        $_date = left($_datetime, InStr($_datetime, ' ') - 1) 
        $_time = SubStr($_datetime, InStr($_datetime, ' ') + 1) 
       Case InStr($_datetime,'/') 
        $_date = $_datetime 
        $_time = '00:00:00' 
       Case InStr($_datetime,':') 
        $_date = @DATE 
        $_time = $_datetime 
       Case 1 
        $_date = @DATE 
        $_time = @TIME 
      EndSelect 
      If $_date And $_time 
        $_datetime = Join(Split($_date, '/'), '') + Join(Split($_time, ':'), '') + '.000000' + $_timezone 
      Else 
        $_datetime = '' 
      EndIf 
 
      $_wqlQuery = $_wqlQuery + ' AND TimeGenerated>="' + $_datetime + '"' 
    EndIf 
  EndIf 
 
  $_objWMIResults =  $_objWBEM.ExecQuery($_wqlQuery, 'WQL', 48) 
  If @ERROR 
    Exit @ERROR 
  EndIf 
 
  $_rownumber = 0 
  $_columnnumber = 0 
 
  For Each $_event In $_objWMIResults 
    If $_rownumber Mod $_arrayrows = 0 
      ReDim Preserve $_eventarray[$_rownumber + $_arrayrows] 
    EndIf 
    $_eventarray[$_rownumber] = $_event.Properties_ 
    $_rownumber = $_rownumber + 1 
  Next 
  If $_rownumber 
    ReDim Preserve $_eventarray[$_rownumber - 1] 
  Else 
    $ReadEventlog = '' 
;    return ; GB: RETURN??? This isn't a subroutine - Replaced with Exit 0 
    Exit 0
  EndIf 
 
  ReDim $ReadEventlog[$_rownumber-1, $_arraycolumns - 1] 
  $_rownumber = 0 
  For Each $_event In $_eventarray 
    $_columnnumber = 0 
    For Each $_item In $_event 
     $_itemname = $_item.name 
     $_itemvalue = $_item.value 
     If $_customwql = 0 Or AScan($_customfields,$_itemname) + 1 
       Select 
        Case $_itemname = 'Data' 
         $_datastring = '' 
         For Each $_byte In $_item.value 
           If $_byte = 0 
             $_byte = 46 
           EndIf 
           $_datastring = $_datastring + chr($_byte) 
          Next 
          $ReadEventlog[$_rownumber,$_columnnumber] = $_datastring 
         Case $_itemname = 'InsertionStrings' 
          $ReadEventlog[$_rownumber, $_columnnumber] = Join($_itemValue, @CRLF) 
         Case $_itemname = 'TimeGenerated' Or $_itemName = 'TimeWritten' 
          $_time = Left($_itemValue, 4) + '/' + SubStr($_itemValue, 5, 2) + '/' + SubStr($_itemValue, 7, 2) + ' ' 
          $_time = $_time + SubStr($_itemValue, 9, 2) + ':' + SubStr($_itemValue, 11, 2) + ':' + SubStr($_itemValue, 13, 2) 
          $ReadEventlog[$_rownumber, $_columnnumber] = $_time 
         Case 1 
          $ReadEventlog[$_rownumber, $_columnnumber] = $_itemValue 
        EndSelect 
        $_columnnumber = $_columnnumber + 1 
      EndIf 
    Next 
    $_rownumber = $_rownumber + 1 
  Next 
 
  $_objWMIResults = 0 
  $_objWBEM = 0 
  $_objLocator = 0 
 
  Exit 0 
 
EndFunction