...

Source file src/github.com/Microsoft/hcsshim/internal/winapi/utils.go

Documentation: github.com/Microsoft/hcsshim/internal/winapi

     1  //go:build windows
     2  
     3  package winapi
     4  
     5  import (
     6  	"errors"
     7  	"reflect"
     8  	"syscall"
     9  	"unsafe"
    10  
    11  	"golang.org/x/sys/windows"
    12  )
    13  
    14  // Uint16BufferToSlice wraps a uint16 pointer-and-length into a slice
    15  // for easier interop with Go APIs
    16  func Uint16BufferToSlice(buffer *uint16, bufferLength int) (result []uint16) {
    17  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&result))
    18  	hdr.Data = uintptr(unsafe.Pointer(buffer))
    19  	hdr.Cap = bufferLength
    20  	hdr.Len = bufferLength
    21  
    22  	return
    23  }
    24  
    25  // UnicodeString corresponds to UNICODE_STRING win32 struct defined here
    26  // https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string
    27  type UnicodeString struct {
    28  	Length        uint16
    29  	MaximumLength uint16
    30  	Buffer        *uint16
    31  }
    32  
    33  // NTSTRSAFE_UNICODE_STRING_MAX_CCH is a constant defined in ntstrsafe.h. This value
    34  // denotes the maximum number of wide chars a path can have.
    35  const NTSTRSAFE_UNICODE_STRING_MAX_CCH = 32767
    36  
    37  // String converts a UnicodeString to a golang string
    38  func (uni UnicodeString) String() string {
    39  	// UnicodeString is not guaranteed to be null terminated, therefore
    40  	// use the UnicodeString's Length field
    41  	return windows.UTF16ToString(Uint16BufferToSlice(uni.Buffer, int(uni.Length/2)))
    42  }
    43  
    44  // NewUnicodeString allocates a new UnicodeString and copies `s` into
    45  // the buffer of the new UnicodeString.
    46  func NewUnicodeString(s string) (*UnicodeString, error) {
    47  	buf, err := windows.UTF16FromString(s)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	if len(buf) > NTSTRSAFE_UNICODE_STRING_MAX_CCH {
    53  		return nil, syscall.ENAMETOOLONG
    54  	}
    55  
    56  	uni := &UnicodeString{
    57  		// The length is in bytes and should not include the trailing null character.
    58  		Length:        uint16((len(buf) - 1) * 2),
    59  		MaximumLength: uint16((len(buf) - 1) * 2),
    60  		Buffer:        &buf[0],
    61  	}
    62  	return uni, nil
    63  }
    64  
    65  // ConvertStringSetToSlice is a helper function used to convert the contents of
    66  // `buf` into a string slice. `buf` contains a set of null terminated strings
    67  // with an additional null at the end to indicate the end of the set.
    68  func ConvertStringSetToSlice(buf []byte) ([]string, error) {
    69  	var results []string
    70  	prev := 0
    71  	for i := range buf {
    72  		if buf[i] == 0 {
    73  			if prev == i {
    74  				// found two null characters in a row, return result
    75  				return results, nil
    76  			}
    77  			results = append(results, string(buf[prev:i]))
    78  			prev = i + 1
    79  		}
    80  	}
    81  	return nil, errors.New("string set malformed: missing null terminator at end of buffer")
    82  }
    83  

View as plain text