github.com/r3vit/terraform@v0.11.9-beta1.0.20181016131357-87d05607d3c5/state/local_lock_windows.go (about)

     1  // +build windows
     2  
     3  package state
     4  
     5  import (
     6  	"math"
     7  	"syscall"
     8  	"unsafe"
     9  )
    10  
    11  var (
    12  	modkernel32      = syscall.NewLazyDLL("kernel32.dll")
    13  	procLockFileEx   = modkernel32.NewProc("LockFileEx")
    14  	procCreateEventW = modkernel32.NewProc("CreateEventW")
    15  )
    16  
    17  const (
    18  	// dwFlags defined for LockFileEx
    19  	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
    20  	_LOCKFILE_FAIL_IMMEDIATELY = 1
    21  	_LOCKFILE_EXCLUSIVE_LOCK   = 2
    22  )
    23  
    24  func (s *LocalState) lock() error {
    25  	// even though we're failing immediately, an overlapped event structure is
    26  	// required
    27  	ol, err := newOverlapped()
    28  	if err != nil {
    29  		return err
    30  	}
    31  	defer syscall.CloseHandle(ol.HEvent)
    32  
    33  	return lockFileEx(
    34  		syscall.Handle(s.stateFileOut.Fd()),
    35  		_LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY,
    36  		0,              // reserved
    37  		0,              // bytes low
    38  		math.MaxUint32, // bytes high
    39  		ol,
    40  	)
    41  }
    42  
    43  func (s *LocalState) unlock() error {
    44  	// the file is closed in Unlock
    45  	return nil
    46  }
    47  
    48  func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
    49  	r1, _, e1 := syscall.Syscall6(
    50  		procLockFileEx.Addr(),
    51  		6,
    52  		uintptr(h),
    53  		uintptr(flags),
    54  		uintptr(reserved),
    55  		uintptr(locklow),
    56  		uintptr(lockhigh),
    57  		uintptr(unsafe.Pointer(ol)),
    58  	)
    59  	if r1 == 0 {
    60  		if e1 != 0 {
    61  			err = error(e1)
    62  		} else {
    63  			err = syscall.EINVAL
    64  		}
    65  	}
    66  	return
    67  }
    68  
    69  // newOverlapped creates a structure used to track asynchronous
    70  // I/O requests that have been issued.
    71  func newOverlapped() (*syscall.Overlapped, error) {
    72  	event, err := createEvent(nil, true, false, nil)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return &syscall.Overlapped{HEvent: event}, nil
    77  }
    78  
    79  func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
    80  	var _p0 uint32
    81  	if manualReset {
    82  		_p0 = 1
    83  	}
    84  	var _p1 uint32
    85  	if initialState {
    86  		_p1 = 1
    87  	}
    88  
    89  	r0, _, e1 := syscall.Syscall6(
    90  		procCreateEventW.Addr(),
    91  		4,
    92  		uintptr(unsafe.Pointer(sa)),
    93  		uintptr(_p0),
    94  		uintptr(_p1),
    95  		uintptr(unsafe.Pointer(name)),
    96  		0,
    97  		0,
    98  	)
    99  	handle = syscall.Handle(r0)
   100  	if handle == syscall.InvalidHandle {
   101  		if e1 != 0 {
   102  			err = error(e1)
   103  		} else {
   104  			err = syscall.EINVAL
   105  		}
   106  	}
   107  	return
   108  }