github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/states/statemgr/filesystem_lock_windows.go (about)

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