github.com/phuslu/log@v1.0.100/eventlog.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package log
     5  
     6  import (
     7  	"errors"
     8  	"sync"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  // EventlogWriter is an Writer that writes logs to windows event log.
    14  type EventlogWriter struct {
    15  	// Event Source, must not be empty
    16  	Source string
    17  
    18  	// Event ID, using `eid` key in log event if not empty
    19  	ID uintptr
    20  
    21  	// Event Host, optional
    22  	Host string
    23  
    24  	once       sync.Once
    25  	register   *syscall.LazyProc
    26  	deregister *syscall.LazyProc
    27  	report     *syscall.LazyProc
    28  	handle     uintptr
    29  }
    30  
    31  // Write implements io.Closer.
    32  func (w *EventlogWriter) Close() (err error) {
    33  	var ret uintptr
    34  	ret, _, err = syscall.Syscall(w.deregister.Addr(), 1, w.handle, 0, 0)
    35  	if ret > 0 {
    36  		err = nil
    37  	}
    38  	return
    39  }
    40  
    41  // WriteEntry implements Writer.
    42  func (w *EventlogWriter) WriteEntry(e *Entry) (n int, err error) {
    43  	w.once.Do(func() {
    44  		if w.ID == 0 {
    45  			err = errors.New("Specify eventlog default id")
    46  			return
    47  		}
    48  
    49  		if w.Source == "" {
    50  			err = errors.New("Specify eventlog source")
    51  			return
    52  		}
    53  
    54  		var s *uint16
    55  		if w.Host != "" {
    56  			s = syscall.StringToUTF16Ptr(w.Host)
    57  		}
    58  
    59  		advapi32 := syscall.NewLazyDLL("advapi32.dll")
    60  		w.register = advapi32.NewProc("RegisterEventSourceW")
    61  		w.deregister = advapi32.NewProc("DeregisterEventSource")
    62  		w.report = advapi32.NewProc("ReportEventW")
    63  
    64  		w.handle, _, err = syscall.Syscall(w.register.Addr(), 2, uintptr(unsafe.Pointer(s)), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(w.Source))), 0)
    65  		if w.handle != 0 {
    66  			err = nil
    67  		}
    68  	})
    69  
    70  	if err != nil {
    71  		return
    72  	}
    73  
    74  	const (
    75  		EVENTLOG_SUCCESS          = 0x0000
    76  		EVENTLOG_ERROR_TYPE       = 0x0001
    77  		EVENTLOG_WARNING_TYPE     = 0x0002
    78  		EVENTLOG_INFORMATION_TYPE = 0x0004
    79  		EVENTLOG_AUDIT_SUCCESS    = 0x0008
    80  		EVENTLOG_AUDIT_FAILURE    = 0x0010
    81  	)
    82  
    83  	var etype uint16
    84  	switch e.Level {
    85  	case TraceLevel:
    86  		etype = EVENTLOG_INFORMATION_TYPE
    87  	case DebugLevel:
    88  		etype = EVENTLOG_INFORMATION_TYPE
    89  	case InfoLevel:
    90  		etype = EVENTLOG_INFORMATION_TYPE
    91  	case WarnLevel:
    92  		etype = EVENTLOG_WARNING_TYPE
    93  	case ErrorLevel:
    94  		etype = EVENTLOG_ERROR_TYPE
    95  	case FatalLevel:
    96  		etype = EVENTLOG_AUDIT_FAILURE
    97  	case PanicLevel:
    98  		etype = EVENTLOG_AUDIT_FAILURE
    99  	default:
   100  		etype = EVENTLOG_INFORMATION_TYPE
   101  	}
   102  
   103  	var ecat uintptr = 0
   104  	var eid = w.ID
   105  	var ss = []*uint16{syscall.StringToUTF16Ptr(b2s(e.buf))}
   106  
   107  	var ret uintptr
   108  	ret, _, err = syscall.Syscall9(w.report.Addr(), 9, w.handle, uintptr(etype), ecat, eid, 0, 1, 0, uintptr(unsafe.Pointer(&ss[0])), 0)
   109  	if ret > 0 {
   110  		err = nil
   111  	}
   112  	if err == nil {
   113  		n = len(e.buf)
   114  	}
   115  
   116  	return
   117  }
   118  
   119  var _ Writer = (*EventlogWriter)(nil)