77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
// Copyright 2015 Tim Heckman. All rights reserved.
|
|
// Use of this source code is governed by the BSD 3-Clause
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build windows
|
|
|
|
package flock
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
kernel32, _ = syscall.LoadLibrary("kernel32.dll")
|
|
procLockFileEx, _ = syscall.GetProcAddress(kernel32, "LockFileEx")
|
|
procUnlockFileEx, _ = syscall.GetProcAddress(kernel32, "UnlockFileEx")
|
|
)
|
|
|
|
const (
|
|
winLockfileFailImmediately = 0x00000001
|
|
winLockfileExclusiveLock = 0x00000002
|
|
winLockfileSharedLock = 0x00000000
|
|
)
|
|
|
|
// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows
|
|
// `LockFileEX` docs, which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
|
|
//
|
|
// > The function requests an exclusive lock. Otherwise, it requests a shared
|
|
// > lock.
|
|
//
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
|
|
|
|
func lockFileEx(handle syscall.Handle, flags uint32, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
|
|
r1, _, errNo := syscall.Syscall6(
|
|
uintptr(procLockFileEx),
|
|
6,
|
|
uintptr(handle),
|
|
uintptr(flags),
|
|
uintptr(reserved),
|
|
uintptr(numberOfBytesToLockLow),
|
|
uintptr(numberOfBytesToLockHigh),
|
|
uintptr(unsafe.Pointer(offset)))
|
|
|
|
if r1 != 1 {
|
|
if errNo == 0 {
|
|
return false, syscall.EINVAL
|
|
}
|
|
|
|
return false, errNo
|
|
}
|
|
|
|
return true, 0
|
|
}
|
|
|
|
func unlockFileEx(handle syscall.Handle, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
|
|
r1, _, errNo := syscall.Syscall6(
|
|
uintptr(procUnlockFileEx),
|
|
5,
|
|
uintptr(handle),
|
|
uintptr(reserved),
|
|
uintptr(numberOfBytesToLockLow),
|
|
uintptr(numberOfBytesToLockHigh),
|
|
uintptr(unsafe.Pointer(offset)),
|
|
0)
|
|
|
|
if r1 != 1 {
|
|
if errNo == 0 {
|
|
return false, syscall.EINVAL
|
|
}
|
|
|
|
return false, errNo
|
|
}
|
|
|
|
return true, 0
|
|
}
|