//go:build windows
|
|
package singleinstance
|
|
import (
|
"fmt"
|
"syscall"
|
"unsafe"
|
)
|
|
var (
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
procCreateMutex = kernel32.NewProc("CreateMutexW")
|
procReleaseMutex = kernel32.NewProc("ReleaseMutex")
|
procCloseHandle = kernel32.NewProc("CloseHandle")
|
)
|
|
const errorAlreadyExists = 183
|
|
type windowsLock struct {
|
handle syscall.Handle
|
}
|
|
// Acquire tries to acquire a named mutex. Returns error if another instance holds it.
|
func Acquire() (Lock, error) {
|
name, err := syscall.UTF16PtrFromString("Global\\VoiceSnapSingleInstance")
|
if err != nil {
|
return nil, err
|
}
|
|
handle, _, err := procCreateMutex.Call(0, 0, uintptr(unsafe.Pointer(name)))
|
if handle == 0 {
|
return nil, fmt.Errorf("CreateMutex failed: %v", err)
|
}
|
|
if err.(syscall.Errno) == errorAlreadyExists {
|
procCloseHandle.Call(handle)
|
return nil, fmt.Errorf("another instance is already running")
|
}
|
|
return &windowsLock{handle: syscall.Handle(handle)}, nil
|
}
|
|
func (l *windowsLock) Release() {
|
if l.handle != 0 {
|
procReleaseMutex.Call(uintptr(l.handle))
|
procCloseHandle.Call(uintptr(l.handle))
|
l.handle = 0
|
}
|
}
|