| //go:build windows |
| // +build windows |
| |
| package clistate |
| |
| import ( |
| "math" |
| "syscall" |
| "unsafe" |
| ) |
| |
| var ( |
| modkernel32 = syscall.NewLazyDLL("kernel32.dll") |
| procLockFileEx = modkernel32.NewProc("LockFileEx") |
| procCreateEventW = modkernel32.NewProc("CreateEventW") |
| ) |
| |
| const ( |
| // dwFlags defined for LockFileEx |
| // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx |
| _LOCKFILE_FAIL_IMMEDIATELY = 1 |
| _LOCKFILE_EXCLUSIVE_LOCK = 2 |
| ) |
| |
| func (s *LocalState) lock() error { |
| // even though we're failing immediately, an overlapped event structure is |
| // required |
| ol, err := newOverlapped() |
| if err != nil { |
| return err |
| } |
| defer syscall.CloseHandle(ol.HEvent) |
| |
| return lockFileEx( |
| syscall.Handle(s.stateFileOut.Fd()), |
| _LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY, |
| 0, // reserved |
| 0, // bytes low |
| math.MaxUint32, // bytes high |
| ol, |
| ) |
| } |
| |
| func (s *LocalState) unlock() error { |
| // the file is closed in Unlock |
| return nil |
| } |
| |
| func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { |
| r1, _, e1 := syscall.Syscall6( |
| procLockFileEx.Addr(), |
| 6, |
| uintptr(h), |
| uintptr(flags), |
| uintptr(reserved), |
| uintptr(locklow), |
| uintptr(lockhigh), |
| uintptr(unsafe.Pointer(ol)), |
| ) |
| if r1 == 0 { |
| if e1 != 0 { |
| err = error(e1) |
| } else { |
| err = syscall.EINVAL |
| } |
| } |
| return |
| } |
| |
| // newOverlapped creates a structure used to track asynchronous |
| // I/O requests that have been issued. |
| func newOverlapped() (*syscall.Overlapped, error) { |
| event, err := createEvent(nil, true, false, nil) |
| if err != nil { |
| return nil, err |
| } |
| return &syscall.Overlapped{HEvent: event}, nil |
| } |
| |
| func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) { |
| var _p0 uint32 |
| if manualReset { |
| _p0 = 1 |
| } |
| var _p1 uint32 |
| if initialState { |
| _p1 = 1 |
| } |
| |
| r0, _, e1 := syscall.Syscall6( |
| procCreateEventW.Addr(), |
| 4, |
| uintptr(unsafe.Pointer(sa)), |
| uintptr(_p0), |
| uintptr(_p1), |
| uintptr(unsafe.Pointer(name)), |
| 0, |
| 0, |
| ) |
| handle = syscall.Handle(r0) |
| if handle == syscall.InvalidHandle { |
| if e1 != 0 { |
| err = error(e1) |
| } else { |
| err = syscall.EINVAL |
| } |
| } |
| return |
| } |