src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/sys/ewindows/wait.go (about)

     1  //go:build windows
     2  
     3  package ewindows
     4  
     5  import (
     6  	"errors"
     7  	"unsafe"
     8  
     9  	"golang.org/x/sys/windows"
    10  )
    11  
    12  const (
    13  	INFINITE = 0xFFFFFFFF
    14  )
    15  
    16  const (
    17  	WAIT_OBJECT_0    = 0
    18  	WAIT_ABANDONED_0 = 0x00000080
    19  	WAIT_TIMEOUT     = 0x00000102
    20  	WAIT_FAILED      = 0xFFFFFFFF
    21  )
    22  
    23  var (
    24  	waitForMultipleObjects = kernel32.NewProc("WaitForMultipleObjects")
    25  	errTimeout             = errors.New("WaitForMultipleObjects timeout")
    26  )
    27  
    28  // WaitForMultipleObjects blocks until any of the objects is triggered or
    29  // timeout.
    30  //
    31  // DWORD WINAPI WaitForMultipleObjects(
    32  //
    33  //	_In_       DWORD  nCount,
    34  //	_In_ const HANDLE *lpHandles,
    35  //	_In_       BOOL   bWaitAll,
    36  //	_In_       DWORD  dwMilliseconds
    37  //
    38  // );
    39  func WaitForMultipleObjects(handles []windows.Handle, waitAll bool,
    40  	timeout uint32) (trigger int, abandoned bool, err error) {
    41  
    42  	count := uintptr(len(handles))
    43  	ret, _, err := waitForMultipleObjects.Call(count,
    44  		uintptr(unsafe.Pointer(&handles[0])), boolToUintptr(waitAll), uintptr(timeout))
    45  	switch {
    46  	case WAIT_OBJECT_0 <= ret && ret < WAIT_OBJECT_0+count:
    47  		return int(ret - WAIT_OBJECT_0), false, nil
    48  	case WAIT_ABANDONED_0 <= ret && ret < WAIT_ABANDONED_0+count:
    49  		return int(ret - WAIT_ABANDONED_0), true, nil
    50  	case ret == WAIT_TIMEOUT:
    51  		return -1, false, errTimeout
    52  	default:
    53  		return -1, false, err
    54  	}
    55  }
    56  
    57  func boolToUintptr(b bool) uintptr {
    58  	if b {
    59  		return 1
    60  	}
    61  	return 0
    62  }