-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ import ( | |
"unsafe" | ||
) | ||
|
||
// EventlogWriter is an Writer that writes logs to windows event log. | ||
// EventlogWriter is a Writer that writes logs to windows event log. | ||
type EventlogWriter struct { | ||
// Event Source, must not be empty | ||
Source string | ||
|
@@ -20,56 +20,79 @@ type EventlogWriter struct { | |
// Event Host, optional | ||
Host string | ||
|
||
once sync.Once | ||
register *syscall.LazyProc | ||
deregister *syscall.LazyProc | ||
report *syscall.LazyProc | ||
handle uintptr | ||
mu sync.Mutex | ||
handle uintptr | ||
} | ||
|
||
var ( | ||
advapi32 = syscall.NewLazyDLL("advapi32.dll") | ||
procRegisterEventSourceW = advapi32.NewProc("RegisterEventSourceW") | ||
procDeregisterEventSource = advapi32.NewProc("DeregisterEventSource") | ||
procReportEventW = advapi32.NewProc("ReportEventW") | ||
) | ||
|
||
// Write implements io.Closer. | ||
func (w *EventlogWriter) Close() (err error) { | ||
var ret uintptr | ||
ret, _, err = syscall.Syscall(w.deregister.Addr(), 1, w.handle, 0, 0) | ||
ret, _, err = syscall.Syscall(procDeregisterEventSource.Addr(), 1, w.handle, 0, 0) | ||
if ret > 0 { | ||
err = nil | ||
} | ||
return | ||
} | ||
|
||
// WriteEntry implements Writer. | ||
func (w *EventlogWriter) WriteEntry(e *Entry) (n int, err error) { | ||
w.once.Do(func() { | ||
if w.ID == 0 { | ||
err = errors.New("Specify eventlog default id") | ||
return | ||
} | ||
|
||
if w.Source == "" { | ||
err = errors.New("Specify eventlog source") | ||
return | ||
} | ||
func (w *EventlogWriter) connect() (err error) { | ||
if w.handle != 0 { | ||
w.Close() | ||
w.handle = 0 | ||
} | ||
|
||
var s *uint16 | ||
if w.Host != "" { | ||
s = syscall.StringToUTF16Ptr(w.Host) | ||
} | ||
if w.ID == 0 { | ||
err = errors.New("Specify eventlog default id") | ||
return | ||
} | ||
|
||
advapi32 := syscall.NewLazyDLL("advapi32.dll") | ||
w.register = advapi32.NewProc("RegisterEventSourceW") | ||
w.deregister = advapi32.NewProc("DeregisterEventSource") | ||
w.report = advapi32.NewProc("ReportEventW") | ||
if w.Source == "" { | ||
err = errors.New("Specify eventlog source") | ||
return | ||
} | ||
|
||
w.handle, _, err = syscall.Syscall(w.register.Addr(), 2, uintptr(unsafe.Pointer(s)), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(w.Source))), 0) | ||
if w.handle != 0 { | ||
err = nil | ||
var host *uint16 | ||
if w.Host != "" { | ||
host, err = syscall.UTF16PtrFromString(w.Host) | ||
if err != nil { | ||
return | ||
} | ||
}) | ||
} | ||
|
||
var source *uint16 | ||
source, err = syscall.UTF16PtrFromString(w.Source) | ||
if err != nil { | ||
return | ||
} | ||
|
||
w.handle, _, err = syscall.Syscall(procRegisterEventSourceW.Addr(), 2, uintptr(unsafe.Pointer(host)), uintptr(unsafe.Pointer(source)), 0) | ||
if w.handle != 0 { | ||
err = nil | ||
} | ||
|
||
return | ||
} | ||
|
||
// WriteEntry implements Writer. | ||
func (w *EventlogWriter) WriteEntry(e *Entry) (n int, err error) { | ||
if w.handle == 0 { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
xuyang2
Contributor
|
||
w.mu.Lock() | ||
if w.handle == 0 { | ||
err = w.connect() | ||
if err != nil { | ||
w.mu.Unlock() | ||
return | ||
} | ||
} | ||
w.mu.Unlock() | ||
} | ||
|
||
const ( | ||
EVENTLOG_SUCCESS = 0x0000 | ||
EVENTLOG_ERROR_TYPE = 0x0001 | ||
|
@@ -101,10 +124,15 @@ func (w *EventlogWriter) WriteEntry(e *Entry) (n int, err error) { | |
|
||
var ecat uintptr = 0 | ||
var eid = w.ID | ||
var ss = []*uint16{syscall.StringToUTF16Ptr(b2s(e.buf))} | ||
var ss = []*uint16{nil} | ||
|
||
ss[0], err = syscall.UTF16PtrFromString(b2s(e.buf)) | ||
if err != nil { | ||
return | ||
} | ||
|
||
var ret uintptr | ||
ret, _, err = syscall.Syscall9(w.report.Addr(), 9, w.handle, uintptr(etype), ecat, eid, 0, 1, 0, uintptr(unsafe.Pointer(&ss[0])), 0) | ||
ret, _, err = syscall.Syscall9(procReportEventW.Addr(), 9, w.handle, uintptr(etype), ecat, eid, 0, 1, 0, uintptr(unsafe.Pointer(&ss[0])), 0) | ||
if ret > 0 { | ||
err = nil | ||
} | ||
|
syscall 包的 LazyDLL/LazyProc 在加锁之前的
if ... == nil
用的也是 Race-detector-friendly versiongolang/go@9b4aaa4
https://golang.org/cl/6856046
还有 sync.Once.Do() 的第一个判断也是用的 Race-detector-friendly version
https://github.com/golang/go/blob/go1.16/src/sync/once.go#L57
https://github.com/golang/go/blob/go1.16/src/sync/once.go#L67