⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stntlog.pas

📁 条码控件: 一维条码控件 二维条码控件 PDF417Barcode MaxiCodeBarcode
💻 PAS
字号:
(* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is TurboPower SysTools
 *
 * The Initial Developer of the Original Code is
 * TurboPower Software
 *
 * Portions created by the Initial Developer are Copyright (C) 1996-2002
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** *)

{*********************************************************}
{* SysTools: StNTLog.pas 4.03                            *}
{*********************************************************}
{* SysTools: NT Event Logging                            *}
{*********************************************************}

{$I StDefine.inc}

unit StNTLog;

interface

uses
  Windows, SysUtils, Classes, Registry, StBase;

type

  TStNTEventType = (etSuccess, etError, etWarning, etInfo,
    etAuditSuccess, etAuditFailure);

  PStNTEventLogRec = ^TStNTEventLogRec;
  TStNTEventLogRec = record
    case Integer of
      0 : (Length              : DWORD;  { Length of full record }
           Reserved            : DWORD;  { Used by the service }
           RecordNumber        : DWORD;  { Absolute record number }
           TimeGenerated       : DWORD;  { Seconds since 1-1-1970 }
           TimeWritten         : DWORD;  { Seconds since 1-1-1970 }
           EventID             : DWORD;
           EventType           : WORD;
           NumStrings          : WORD;
           EventCategory       : WORD;
           ReservedFlags       : WORD;   { For use with paired events (auditing) }
           ClosingRecordNumber : DWORD;  { For use with paired events (auditing) }
           StringOffset        : DWORD;  { Offset from beginning of record }
           UserSidLength       : DWORD;
           UserSidOffset       : DWORD;
           DataLength          : DWORD;
           DataOffset          : DWORD); { Offset from beginning of record }

      1 : (VarData : array [0..65535] of Byte);

    //
    // Variable data may contain:
    //
    // WCHAR SourceName[]
    // WCHAR Computername[]
    // SID   UserSid
    // WCHAR Strings[]
    // BYTE  Data[]
    // CHAR  Pad[]
    // DWORD Length;
    //
    // Data is contained -after- the static data, the VarData field is set
    // to the beginning of the record merely to make the offsets match up.
  end;

  TStReadRecordEvent = procedure(Sender : TObject; const EventRec : TStNTEventLogRec;
    var Abort : Boolean) of object;

  TStNTEventLog = class(TStComponent)
  private
    { Internal use variables }
    elLogHandle : THandle;
    elLogList : TStringList;
    { Property variables }
    FComputerName : string;
    FEnabled : Boolean;
    FEventSource : string;
    FLogName : string;
    FOnReadRecord : TStReadRecordEvent;
  protected
    { Internal Methods }
    procedure elAddEntry(const EventType : TStNTEventType; EventCategory, EventID : DWORD;
      const Strings : TStrings; DataPtr : pointer; DataSize : DWORD);
    procedure elCloseLog;
    procedure elOpenLog;
    { Property Methods }
    function GetLogCount : DWORD;
    function GetLogs(Index : Integer) : string;
    function GetRecordCount : DWORD;
    procedure SetComputerName(const Value : string);
    procedure SetLogName(const Value : string);
  public
    { Public Methods }
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    procedure AddEntry(const EventType : TStNTEventType; EventCategory, EventID : DWORD);
    procedure AddEntryEx(const EventType : TStNTEventType; EventCategory, EventID : DWORD;
      const Strings : TStrings; DataPtr : pointer; DataSize : DWORD);
    procedure ClearLog(const BackupName : TFileName);
    procedure CreateBackup(const BackupName : TFileName);
    procedure ReadLog(const Reverse : Boolean);
    procedure RefreshLogList;
    { Public Properties }
    property LogCount : DWORD read GetLogCount;
    property Logs[Index : Integer] : string read GetLogs;
    property RecordCount : DWORD read GetRecordCount;
  published
    { Published Properties }
    property ComputerName : string read FComputerName write SetComputerName;
    property Enabled : Boolean read FEnabled write FEnabled default True;
    property EventSource : string read FEventSource write FEventSource;
    property LogName : string read FLogName write SetLogName;
    property OnReadRecord : TStReadRecordEvent read FOnReadRecord write FOnReadRecord;
  end;

implementation

const
  { Defines for the READ flags for Eventlogging }

  EVENTLOG_SEQUENTIAL_READ = $0001;
  EVENTLOG_SEEK_READ       = $0002;
  EVENTLOG_FORWARDS_READ   = $0004;
  EVENTLOG_BACKWARDS_READ  = $0008;

  { The types of events that can be logged. }

  EVENTLOG_SUCCESS          = $0000;
  EVENTLOG_ERROR_TYPE       = $0001;
  EVENTLOG_WARNING_TYPE     = $0002;
  EVENTLOG_INFORMATION_TYPE = $0004;
  EVENTLOG_AUDIT_SUCCESS    = $0008;
  EVENTLOG_AUDIT_FAILURE    = $0010;

  { Defines for the WRITE flags used by Auditing for paired events }
  { These are not implemented in Product 1 }

  EVENTLOG_START_PAIRED_EVENT    = $0001;
  EVENTLOG_END_PAIRED_EVENT      = $0002;
  EVENTLOG_END_ALL_PAIRED_EVENTS = $0004;
  EVENTLOG_PAIRED_EVENT_ACTIVE   = $0008;
  EVENTLOG_PAIRED_EVENT_INACTIVE = $0010;

  StEventLogKey = '\SYSTEM\CurrentControlSet\Services\EventLog';

  
{ Create instance of event log component }
constructor TStNTEventLog.Create(AOwner : TComponent);
begin
  inherited Create(AOwner);

  { initialization }
  elLogHandle := 0;
  elLogList := TStringList.Create;
  FEnabled := True;
  FLogName := 'Application';

  { initialize log list }
  RefreshLogList;
end;

{ Destroy instance of event log component }
destructor TStNTEventLog.Destroy;
begin
  if elLogHandle <> 0 then elCloseLog;
  elLogList.Free;
  inherited;
end;

{ Add entry to the event log }
procedure TStNTEventLog.AddEntry(const EventType : TStNTEventType;
  EventCategory, EventID : DWORD);
begin
  elAddEntry(EventType, EventCategory, EventID, nil, nil, 0);
end;

{ Add entry to the event log - more options }
procedure TStNTEventLog.AddEntryEx(const EventType : TStNTEventType;
  EventCategory, EventID : DWORD; const Strings : TStrings;
  DataPtr : pointer; DataSize : DWORD);
begin
  elAddEntry(EventType, EventCategory, EventID, Strings, DataPtr, DataSize);
end;

{ Clear the event log }
procedure TStNTEventLog.ClearLog(const BackupName : TFileName);
begin
  elOpenLog;
  try
    ClearEventLog(elLogHandle, PChar(BackupName));
  finally
    elCloseLog;
  end;
end;

{ Back up the event log }
procedure TStNTEventLog.CreateBackup(const BackupName : TFileName);
begin
  elOpenLog;
  try
    BackupEventLog(elLogHandle, PChar(BackupName));
  finally
    elCloseLog;
  end;
end;

{ Adds an entry to the event log }
procedure TStNTEventLog.elAddEntry(const EventType : TStNTEventType;
  EventCategory, EventID : DWORD; const Strings : TStrings; DataPtr : pointer; DataSize : DWORD);
const
  StrArraySize = 1024;
var
  TempType, StrCount : DWORD;
  StrArray : array[0..StrArraySize-1] of PChar;
  StrArrayPtr : pointer;
  I : Integer;
begin
  StrArrayPtr := nil;

  case EventType of
    etSuccess : TempType := EVENTLOG_SUCCESS;
    etError : TempType := EVENTLOG_ERROR_TYPE;
    etWarning : TempType := EVENTLOG_WARNING_TYPE;
    etInfo : TempType := EVENTLOG_INFORMATION_TYPE;
    etAuditSuccess : TempType := EVENTLOG_AUDIT_SUCCESS;
    etAuditFailure : TempType := EVENTLOG_AUDIT_FAILURE;
  else
    TempType := 0;
  end;

  elOpenLog;
  try
    { Fill string array }
    if Assigned(Strings) then begin
      FillChar(StrArray, SizeOf(StrArray), #0);
      StrCount := Strings.Count;
      Assert(StrCount <= StrArraySize);
      for I := 0 to StrCount-1 do begin
        StrArray[I] := StrAlloc(Length(Strings[I]));
        StrPCopy(StrArray[I], Strings[I]);
      end;
      StrArrayPtr := @StrArray;
    end else begin
      StrCount := 0;
    end;
    ReportEvent(elLogHandle, TempType, EventCategory,
      EventID, nil, StrCount, DataSize, StrArrayPtr, DataPtr);
  finally
    { Release string array memory }
    for I := 0 to StrArraySize-1 do begin
      if StrArray[I] = nil then Break;
      StrDispose(StrArray[I]);
    end;
    elCloseLog;
  end;
end;

{ Close event log }
procedure TStNTEventLog.elCloseLog;
begin
  if elLogHandle <> 0 then begin
    CloseEventLog(elLogHandle);
    elLogHandle := 0;
  end;
end;

{ Open event log }
procedure TStNTEventLog.elOpenLog;
begin
  if elLogHandle = 0 then
    elLogHandle := OpenEventLog(PChar(FComputerName), PChar(FLogName));
end;

{ Get number on logs available on system }
function TStNTEventLog.GetLogCount : DWORD;
begin
  Result := elLogList.Count;
end;

{ Get name of logs }
function TStNTEventLog.GetLogs(Index : Integer) : string;
begin
  Result := elLogList[Index];
end;

{ Get number of log entries in event log }
function TStNTEventLog.GetRecordCount : DWORD;
begin
  elOpenLog;
  try
    GetNumberOfEventLogRecords(elLogHandle, Result);
  finally
    elCloseLog;
  end;
end;

{ Reads log until complete or aborted }
procedure TStNTEventLog.ReadLog(const Reverse : Boolean);
var
  ReadDir, BytesRead, BytesNeeded, LastErr : DWORD;
  RetVal, Aborted : Boolean;
  TempBuffer : array[0..2047] of Byte;
  TempPointer : Pointer;
  TempRecPtr : PStNTEventLogRec;  { used as an alias, don't actually allocate }
  FakeBuf : AnsiChar;
begin
  Aborted := False;
  TempPointer := nil;

  { Set direction }
  if Reverse then
    ReadDir := EVENTLOG_SEQUENTIAL_READ or EVENTLOG_BACKWARDS_READ
  else
    ReadDir := EVENTLOG_SEQUENTIAL_READ or EVENTLOG_FORWARDS_READ;

  elOpenLog;
  try
    repeat
      { Fake read to determine required buffer size }
      RetVal := ReadEventLog(elLogHandle, ReadDir, 0, @FakeBuf,
        SizeOf(FakeBuf), BytesRead, BytesNeeded);

      if not RetVal then begin
        LastErr := GetLastError;
        if (LastErr = ERROR_INSUFFICIENT_BUFFER) then begin

          { We can use local buffer, which is faster }
          if (BytesNeeded <= SizeOf(TempBuffer)) then begin
            if not (ReadEventLog(elLogHandle, ReadDir, 0, @TempBuffer,
              BytesNeeded, BytesRead, BytesNeeded)) then
              {$WARNINGS OFF}  { Yeah, we know RaiseLastWin32Error is deprecated }
              RaiseLastWin32Error;
              {$WARNINGS ON}

            TempRecPtr := @TempBuffer

          { Local buffer too small, need to allocate a buffer on the heap }
          end else begin
            if TempPointer = nil then
              GetMem(TempPointer, BytesNeeded)
            else
              ReallocMem(TempPointer, BytesNeeded);

            if not (ReadEventLog(elLogHandle, ReadDir, 0, TempPointer,
              BytesNeeded, BytesRead, BytesNeeded)) then
              {$WARNINGS OFF}  { Yeah, we know RaiseLastWin32Error is deprecated }
              RaiseLastWin32Error;
              {$WARNINGS ON}

            TempRecPtr := TempPointer;

          end;

          { At this point, we should have the data -- fire the event }
          if Assigned(FOnReadRecord) then
            FOnReadRecord(Self, TempRecPtr^, Aborted);

        end else begin
          Aborted := True;

          { Handle unexpected error }
          {$WARNINGS OFF}  { Yeah, we know RaiseLastWin32Error is deprecated }
          if (LastErr <> ERROR_HANDLE_EOF) then
            RaiseLastWin32Error;
          {$WARNINGS ON}
        end;
      end;
    until Aborted;

  finally
    elCloseLog;

    if TempPointer = nil then
      FreeMem(TempPointer);
  end;
end;

{ Refreshes log list }
procedure TStNTEventLog.RefreshLogList;
var
  Reg : TRegistry;
begin
  elLogList.Clear;
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey(StEventLogKey, False) then begin
      Reg.GetKeyNames(elLogList);
      Reg.CloseKey;
    end;
  finally
    Reg.Free;
  end;
end;

{ Set log name }
procedure TStNTEventLog.SetLogName(const Value : string);
begin
  FLogName := Value
end;

{ Set computer name }
procedure TStNTEventLog.SetComputerName(const Value : string);
begin
  FComputerName := Value;
  RefreshLogList;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -